これが違法である理由を理解することは役に立ちます。必要な機能は仮パラメーター型共分散であり、それを提供する言語はほとんどありません。(エッフェル、私はこれを機能として持っていると思います。) 安全ではないため、言語ではあまり見られません! 例を挙げて説明しましょう:
class Animal {}
class Lion : Animal { public void Roar() { } }
class Giraffe : Animal { }
interface IFoo { void M(Animal a); }
class C : IFoo
{
public void M(Lion lion) { lion.Roar(); }
}
class P
{
public static void Main()
{
IFoo foo = new C();
foo.M(new Giraffe());
}
}
そして、キリンを鳴らしました。
これらすべての型変換を見ると、合理的に不正にすることができるのは へのマッチングだけC.M(Giraffe)
ですIFoo.M(Animal)
。
現在、仮パラメーターの型の反変性は型安全ですが、非常に限られた状況を除いて、C# では合法ではありません。C# がサポートしていない場合は、次のようなことを安全に行うことができます。
interface IBar { void M(Giraffe g); }
class D : IBar
{
public void M(Animal animal) { ... }
}
class P
{
public static void Main()
{
IBar bar = new D();
bar.M(new Giraffe());
}
}
そこで何が起こったのですか?IFoo.M は「キリンを飼うことができる」と言い、CM は「実際にはどんな動物でも受け入れることができるので、どんなキリンでも受け入れることができる」と言っています。C# がサポートしていればタイプセーフですが、次の 2 つの方法でしかサポートされていません。
- 反変の一般的なデリゲートとインターフェイスの変換。
- デリゲート型への反変メソッド グループ変換。
最初の例は、型の式が同じ論理によってIComparable<Animal>
型の変数に割り当てられる可能性があることですIComparable<Giraffe>
。2 匹の動物を比較する方法は、2 匹のキリンを比較する方法が必要な場合に使用できます。これは C# 4 で追加されました。
2 番目の例は次のとおりです。
delegate void MyFunction(Giraffe g);
...
D d = new D();
MyFunction myfunc = d.M;
ここでも、Giraffe を受け取る関数が必要であり、任意の Animal を受け取る関数を提供します。この機能は C# 2 で追加されました。