2012-02-17 18 views
4

只見喬恩斯基特的演講在NDC 2010不同FW中的協變會導致代碼中斷?

他提到一件趣事:

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?

回答

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 
+0

謝謝@jon是否有任何網站將代碼中斷從第1版改爲第2版? – 2012-02-17 21:03:10

+0

@RoyiNamir:這裏是C#4的一個:http://msdn.microsoft.com/en-us/library/ee855831(v=vs.110).aspx - 我不知道是否有類似的早期版本。 – 2012-02-17 21:04:41

+0

謝謝你的回答。 – 2012-02-17 21:08:34

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); 
相關問題