我在NDC 2010上看到了Jon Skeet的演讲
他提到了一些有趣的事情:
public Class Base
{
public void Foo(IEnumerable<string> strings){}
}
public Class Child:Base
{
publc void Foo(IEnumerable<object> objects) {}
}
Main :
List<string> lst = new List<string>();
lst.Add("aaa");
Child c = new Child();
c.Foo(lst);
使用C#3,它将调用:Base.Foo
使用C#4,它将调用:Child.Foo
我知道这是因为协方差
问题:
是不是有点代码破坏变化? 有没有解决方法,所以这段代码将继续像第3版那样工作?
答案 0 :(得分:7)
是的,这是一个突破性的变化。每当你将一个普遍无效的转换合法化时,这都是一个重大改变。
不幸的是,在不使任何突破性更改的情况下向语言添加功能非常困难。如果真的想要查找它们,那么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
答案 1 :(得分:5)
object x = new List<string>();
if (x is IEnumerable<object>)
Console.WriteLine(4);
else
Console.WriteLine(3);
在C#3中打印3;在C#4中它打印4。
更改类型系统时,可以更改重载决策的结果;就是这样。该功能的好处超过了可能休息的痛苦。
有解决方法吗?是。不要首先打电话给Child.Foo:
Base c = new Child();
c.Foo(list);