2013-06-20 150 views
12

在C#中,所有委託類型彼此不兼容,即使它們具有相同的簽名。舉個例子:爲什麼所有Delegate類型都不相容?

delegate void D1(); 
delegate void D2(); 

D1 d1 = MethodGroup; 
D2 d2 = d1;       // compile time error 
D2 d2 = new D2 (d1);     // you need to do this instead 

這是什麼行爲和語言設計決策背後的原因。

+2

我不能給你的理由,但代表們原來的語言特性。此後,他們添加了lambda方法,[Actions](http://msdn.microsoft.com/en-us/library/system.action.aspx)和[Funcs](http://msdn.microsoft.com/ en-us/library/bb534960.aspx),它們不會遇到同樣的問題。 – Brandon

+0

@Brandon什麼? Lambdas轉換爲代表(或表達式樹),而'Action's和'Func's *只是委託類型,所以它們遵循完全相同的規則。 – svick

+0

委託調用也在運行時檢查。這是優化的,一種重要的優化,只支持嚴格類型標識。這很快。 –

回答

23

In C# all delegate types are incompatible with one another, even if they have the same signature. What is the reasoning behind this behaviour and language design decision?

首先,我認爲這是公平地說,許多運行時和語言設計者的後悔這個決定。代表結構打字 - 即通過簽名進行匹配 - 是一個頻繁要求的功能,而且看起來很奇怪,Func<int, bool>Predicate<int>不能自由分配給對方。

我明白這個決定背後的推理 - 我急於補充說,這個決定是在我開始使用C#團隊之前的大約六年時間做出的 - 期望是會有代表類型語義學。你想這是一個錯誤類型:給出的參數相同時

AnyFunction<int, int> af = x=> { Console.WriteLine(x); return x + y; }; 
PureFunction<int, int> pf = af; 

「純」的功能是產生和消耗無副作用的功能,消耗了它的參數之外的任何信息,並返回一個一致的值。很明顯,af至少失敗了兩個,因此不應將其指定爲pf作爲隱式轉換。

但語義載貨委託類型從來沒有發生過,所以這是一個有點不好的特性的現在。

+1

我必須記住這個詞,'* misfeature *'。 –

+1

我會記得我喜歡短時間內有更多投票的答案,而不是Eric Lippert。 –

15

基本上是因爲編譯器讓兩個班爲您服務。同樣的原因,你不能做的:

class A {} 
class B {} 

void Main() 
{ 
    A a = new A(); 
    B b = a; 
} 

例如,下面的代碼

void Main() {} 

delegate void D(); 
class C {} 

的IL代碼:

D.Invoke: 

D.BeginInvoke: 

D.EndInvoke: 

D..ctor: 

C..ctor: 
IL_0000: ldarg.0  
IL_0001: call  System.Object..ctor 
IL_0006: ret   
2

代表也不過只是另一個類型。由於相同的原因,它們不兼容class A {}class B {}將不兼容。

delegate void D1(); 

將約編譯爲類似:

class D1 : MulticastDelegate { .... } 
相關問題