C#コンパイラエラーCS0080の原因と対策を解説
CS0080は、C#でジェネリックでないクラスやメソッドに対して、型パラメーターの制約を指定しようとすると発生するコンパイルエラーです。
例えば、非ジェネリックな宣言にwhere
句を記述するとこのエラーが出ます。
修正するには、対象をジェネリックにするか、制約指定を削除してください。
エラー発生の原因
このセクションでは、CS0080 エラーの発生原因として考えられる型パラメーター制約の誤用について解説します。
誤った構文で制約を記述すると、コンパイラーはジェネリック宣言が存在しないためエラーを通知します。
型パラメーター制約の誤用
型パラメーター制約は、ジェネリック型やジェネリックメソッドに対してのみ使用できる制約です。
非ジェネリックな宣言に対して where
句を適用すると、CS0080 エラーが発生します。
非ジェネリックなクラスにおけるwhere句の利用
非ジェネリックなクラスに where
句を使用する例は以下のとおりです。
クラス自体がジェネリックでないため、型パラメーターに対する制約を記述できず、コンパイル時に CS0080 エラーとなります。
以下のサンプルコードは、誤った記述例となります。
using System;
namespace SampleNamespace
{
// このクラスはジェネリックではないため、型パラメーター制約は適用できません。
// 以下の行はコンパイルエラー CS0080 を発生させます。
public class MyClass where MyClass : IDisposable
{
public static void Main(string[] args)
{
Console.WriteLine("エラー発生例です");
}
}
}
// コンパイル時に次のようなエラーが表示されます。
// error CS0080: 制約は非ジェネリック宣言では許可されません。
非ジェネリックなメソッドでの制約指定
メソッドがジェネリックでない場合にも、where
句を使用して型パラメーター制約を付けようとすると同様に CS0080 エラーが発生します。
以下は誤った記述例です。
using System;
namespace SampleNamespace
{
public class MyClass
{
// このメソッドはジェネリックではないため、where句を使用できません。
// 以下の行はコンパイルエラー CS0080 を発生させます。
public void Foo() where Foo : new()
{
Console.WriteLine("このメソッドは誤った構文です");
}
public static void Main(string[] args)
{
MyClass instance = new MyClass();
// メソッド呼び出し例(実際には呼び出せません)
Console.WriteLine("エラー発生例です");
}
}
}
// コンパイル時に次のようなエラーが表示されます。
// error CS0080: 制約は非ジェネリック宣言では許可されません。
型パラメーター制約の適用範囲の誤認識
型パラメーター制約は、ジェネリック宣言部分にのみ適用されるものであり、クラスやメソッド自体がジェネリックでなければ利用できません。
制約を適用する対象を誤認識すると、意図しないエラーが発生するため、ジェネリック宣言と制約を正しく対応付ける必要があります。
たとえば、ジェネリック化すべき部分を非ジェネリックのままにしていると、コンパイラーは型パラメーターの存在に違和感を覚え、エラーを出力します。
こうした誤用を防ぐために、対象のクラスやメソッドを最初からジェネリックとして定義するか、不要な where
句を削除することが望ましいです。
エラー修正の方法
ここでは、CS0080 エラーの修正方法について解説します。
エラーを解消する基本的な方法は、ジェネリック宣言への変更と不要な制約の削除の2つに分けられます。
ジェネリック宣言への変更
対象がジェネリックであることが正当である場合は、クラスまたはメソッドの宣言をジェネリックに変更することで CS0080 エラーを解消できます。
クラスのジェネリック化による修正
クラスに対して型パラメーター制約を適用したい場合は、まずクラス自体をジェネリッククラスとして定義する必要があります。
下記のサンプルコードでは、MyClass
をジェネリッククラスに変更し、型パラメーター T
に対して IDisposable
制約を正しく適用しています。
using System;
namespace SampleNamespace
{
// クラスをジェネリックにして、型パラメーター T に対して制約を付与します。
public class MyClass<T> where T : IDisposable
{
public static void Main(string[] args)
{
Console.WriteLine("コンパイル成功の例です");
}
}
}
コンパイル成功の例です
メソッドのジェネリック化による修正
メソッドに型パラメーター制約を適用する場合は、メソッドをジェネリックメソッドとして宣言する必要があります。
以下は、ジェネリックメソッドに where
句を正しく適用したサンプルコードです。
using System;
namespace SampleNamespace
{
// パラメーター制約を適用するため、まずは補助クラス Sample を定義します。
public class Sample
{
public Sample() { }
}
public class MyClass
{
// メソッドをジェネリックメソッドとして宣言し、型パラメーター U に対して new() 制約を付与しています。
public void Foo<U>() where U : new()
{
Console.WriteLine("ジェネリックメソッド 正常な構文です");
}
public static void Main(string[] args)
{
MyClass instance = new MyClass();
instance.Foo<Sample>();
Console.WriteLine("コンパイル成功の例です");
}
}
}
ジェネリックメソッド 正常な構文です
コンパイル成功の例です
制約指定の除去
ジェネリック宣言に変更する必要がない場合は、単純に where
句を削除することで CS0080 エラーを回避できます。
既存の構造で十分な場合には、この対応が適切といえます。
where句を削除する場合の対応
型パラメーター制約が不要であると判断できる場合は、where
句を削除して、非ジェネリックなクラスやメソッドとして正しい構文に変更します。
下記のサンプルコードは、誤った where
句を削除後の例となります。
using System;
namespace SampleNamespace
{
public class MyClass
{
// 不要な where句 を削除して、通常のメソッドとして定義しています。
public void Foo()
{
Console.WriteLine("where句を使用しない正しい構文です");
}
public static void Main(string[] args)
{
MyClass instance = new MyClass();
instance.Foo();
Console.WriteLine("コンパイル成功の例です");
}
}
}
where句を使用しない正しい構文です
コンパイル成功の例です
正しい構文例の検証
このセクションでは、クラスおよびメソッドにおける正しい構文について、サンプルコードを通して確認します。
各サンプルコードは、エラー修正の方法に従って生成された正しい記述例となっております。
サンプルコードによる正例の確認
正しい構文例では、ジェネリックな宣言に対して適切な where
句が設定されるか、不要な場合には削除されています。
これにより、コンパイルエラー CS0080 を回避することができます。
クラスおよびメソッドごとの正しい構文提示
以下のサンプルコードは、クラスをジェネリックに変更した上で、メソッドもジェネリックメソッドとして宣言し、正しい where
句を適用した例です。
このコードは、全体として正しい構文になっており、実行時にエラーは発生しません。
using System;
namespace SampleNamespace
{
// Sample クラスは IDisposable インターフェイスを実装しています。
public class Sample : IDisposable
{
public void Dispose() { }
}
// クラスをジェネリッククラスとして定義し、型パラメーター T に制約を付与しています。
public class MyClass<T> where T : IDisposable
{
// メソッドをジェネリックメソッドとして宣言し、型パラメーター U に new() 制約を付与しています。
public void Foo<U>() where U : new()
{
Console.WriteLine("正しいジェネリックメソッドの利用例です");
}
public static void Main(string[] args)
{
// クラスのジェネリック化の例として、Sample 型を指定します。
MyClass<Sample> instance = new MyClass<Sample>();
// メソッドのジェネリック化の例として、Sample 型を指定します。
instance.Foo<Sample>();
Console.WriteLine("正しい構文のサンプルコードです");
}
}
}
正しいジェネリックメソッドの利用例です
正しい構文のサンプルコードです
まとめ
本記事では、C# コンパイラエラー CS0080 の原因と対策について解説しています。
非ジェネリックなクラスやメソッドで where
句を使用したことがエラーの要因であると説明し、クラスやメソッドをジェネリックに変更する方法、不要な制約を削除する方法の2つのアプローチを示しました。
正しい構文例も提示しており、実際にコードを動かすことでエラー解決の手法を理解できる内容となっています。