不同FW的协方差导致代码中断?

我在NDC 2010上看到了Jon Skeet的演讲

他提到了一些有趣的事

public Class Base { public void Foo(IEnumerable strings){} } public Class Child:Base { publc void Foo(IEnumerable objects) {} } Main : List lst = new List(); lst.Add("aaa"); Child c = new Child(); c.Foo(lst); 

使用C#3,它将调用: Base.Foo

使用C#4,它将调用: Child.Foo

我知道这是因为协方差

题 :

是不是有点代码破坏变化? 有没有解决方法,所以这段代码将继续像第3版那样工作?

是的,这是一个突破性的变化。 每当你将一个普遍无效的转换合法化时,这是一个重大变化。

不幸的是,在没有进行任何重大更改的情况下向语言添加function非常困难。 如果您真的想要寻找它们,那么C#4中还会有更多的事件。 当然,这些不太可能影响大多数开发人员。

在C#1和C#2之间也有类似的重大变化,其中使用的实现在此代码的不同版本之间会发生变化:

 using System; public delegate void StringAction(string x); public class Base { public void Foo(string x) { Console.WriteLine("Base"); } } public class Child : Base { public void Foo(object x) { Console.WriteLine("Child"); } } public class Test { static void Main() { Child c = new Child(); StringAction action = new StringAction(c.Foo); action("x"); } } 

在这种情况下,编译器实际上会发出警告:

 Test.cs(26,31): warning CS1707: Delegate 'StringAction' bound to 'Child.Foo(object)' instead of 'Base.Foo(string)' because of new language rules 

乔恩当然是对的; 这是一个突破性的变化。 更容易看到突破性变化的方法是:

 object x = new List(); if (x is IEnumerable) Console.WriteLine(4); else Console.WriteLine(3); 

在C#3中打印3; 在C#4中它打印4。

更改类型系统时,可以更改重载决策的结果; 就是这样。 该function的好处超过了可能的rest时间的痛苦。

有解决方法吗? 是。 不要首先调用Child.Foo:

 Base c = new Child(); c.Foo(list);