了解为什么这是非法的会很有帮助。您想要的功能是形式参数类型协方差,并且很少有语言提供它。(埃菲尔,我认为这是一个特性。)它在语言中并不常见,因为它不安全!让我用一个例子来说明:
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# 支持它,那将是类型安全的,但它仅以两种方式支持它:
- 逆变泛型委托和接口转换。
- 逆变方法组转换为委托类型。
第一个例子是类型表达式IComparable<Animal>
可以通过相同的逻辑分配给类型变量IComparable<Giraffe>
:在需要比较两只长颈鹿的方法时,可以使用比较两只动物的方法。这是在 C# 4 中添加的。
第二个例子是:
delegate void MyFunction(Giraffe g);
...
D d = new D();
MyFunction myfunc = d.M;
同样,我们需要一个接受 Giraffe 的函数,我们提供一个接受任何 Animal 的函数。此功能是在 C# 2 中添加的。