在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
這是什麼行爲和語言設計決策背後的原因。
在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
這是什麼行爲和語言設計決策背後的原因。
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
作爲隱式轉換。
但語義載貨委託類型從來沒有發生過,所以這是一個有點不好的特性的現在。
我必須記住這個詞,'* misfeature *'。 –
我會記得我喜歡短時間內有更多投票的答案,而不是Eric Lippert。 –
基本上是因爲編譯器讓兩個班爲您服務。同樣的原因,你不能做的:
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
代表也不過只是另一個類型。由於相同的原因,它們不兼容class A {}
和class B {}
將不兼容。
delegate void D1();
將約編譯爲類似:
class D1 : MulticastDelegate { .... }
我不能給你的理由,但代表們原來的語言特性。此後,他們添加了lambda方法,[Actions](http://msdn.microsoft.com/en-us/library/system.action.aspx)和[Funcs](http://msdn.microsoft.com/ en-us/library/bb534960.aspx),它們不會遇到同樣的問題。 – Brandon
@Brandon什麼? Lambdas轉換爲代表(或表達式樹),而'Action's和'Func's *只是委託類型,所以它們遵循完全相同的規則。 – svick
委託調用也在運行時檢查。這是優化的,一種重要的優化,只支持嚴格類型標識。這很快。 –