2013-06-20 3 views
12

C#では、すべてのデリゲート型が同じシグネチャを持っていても、互いに互換性がありません。例として:すべてのデリゲートタイプが互いに互換性がないのはなぜですか?

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

私はあなたに推論を与えることはできませんが、代議員は元の言語機能でした。それ以来、ラムダメソッド[Actions](http://msdn.microsoft.com/en-us/library/system.action.aspx)と[Funcs](http://msdn.microsoft.com/)が追加されています。 en-us/library/bb534960.aspx)には、同じ問題が発生しません。 – Brandon

+0

@Brandon何ですか? Lambdaはデリゲート(または式ツリー)に変換され、 'Action'と' 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#チームを始めてから約6年前にこの決定がなされたことを言い張ります - のデリゲートタイプセマンティクス。同じ引数が与えられたとき、「純粋な」関数が生成し、副作用を消費しない関数は、ある引数の外に何の情報を消費しない、と一貫性のある値を返します

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

:あなたは、これは型エラーになりたいです。暗黙の変換としてpfに割り当てられるべきではないことが明らかなので、少なくともafはそれらのうちの少なくとも2つに失敗します。

しかし、セマンティクスを積んだデリゲート型は決して起こらなかったので、現在は少し間違っています。

+1

私はその言葉を思い出す必要があります、 '* misfeature *'。 –

+1

私はEric Lippertよりも多くの票を得て答えた短い時間を愛しています。 –

15

基本的にコンパイラは2つのクラスを作成するためです。あなたが行うことができないのと同じ理由:たとえば

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 { .... } 
関連する問題