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

Roy*_*mir 4 c# inheritance .net-4.0 covariance

我在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);
Run Code Online (Sandbox Code Playgroud)

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

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

我知道这是因为协方差

题 :

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

Jon*_*eet 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");
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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


Eri*_*ert 5

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

object x = new List<string>();
if (x is IEnumerable<object>) 
    Console.WriteLine(4);
else
    Console.WriteLine(3);
Run Code Online (Sandbox Code Playgroud)

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

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

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

Base c = new Child();
c.Foo(list);
Run Code Online (Sandbox Code Playgroud)