2011-07-22 8 views
7

デリゲートの呼び出しと、通常のメソッド呼び出しが別のメソッドを呼び出す理由を次のコードスニペットデリゲートの共分散とContavariance

namespace ConsoleApplication1 
{ 

public delegate TResult Function<in T, out TResult>(T args); 

class Program 
{ 
     static void Main(string[] args) 
    { 
     Program pg =new Program(); 
     Function<Object, DerivedClass> fn1 = null; 
     Function<String, BaseClass> fn2 = null; 
     fn1 = new Function<object, DerivedClass>(pg.myCheckFuntion) 
     fn2=fn1; 
     fn2("");// calls myCheckFuntion(Object a) 
     pg.myCheckFuntion("Hello"); //calls myCheckFuntion(String a) 
    } 

    public DerivedClass myCheckFuntion(Object a) 
    { 
     return new DerivedClass(); 
    } 
    public DerivedClass myCheckFuntion(String a) 
    { 
     return new DerivedClass(); 
    } 
} 

を考えてみましょう。

答えて

8

デリゲートは、コンパイル時にmyCheckFuntion(Object)にバインドされています。Objectを受け入れる方法を見つけるように指示しています。そのバインディングは単なるメソッドにすぎません。実行時に実際の引数の型に基づいてオーバーロードの解決を行いません。

あなたは"Hello"が文字列で、文字列に文字列からの変換がオーバーロードの解決に反対するために、文字列からの変換よりも優先されるため、は、コンパイル時にmyCheckFuntion(String)に結合することpg.myCheckFuntion("Hello")を呼び出します。

注意あなたが書いたかのよう:myCheckFuntion(Object)を呼び出します、その後

object text = "Hello"; 
pg.myCheckFuntion(text); 

こと。

+0

追加するだけのものはありません。 +1 –

+0

あなたはJon Skeetを破ることはできません! – siride

+0

私のために速すぎる:( – VMAtm

1

デリゲートオブジェクト自体は、1つの関数だけを指していますが、関数の範囲を指していません。 co(ntra)分散は、関数型のより大きな領域でそれを指すことができます。同様に、すべての種類の値をタイプobjectの変数に割り当てることができますが、タイプがstringの変数には少ない値を割り当てることができます。たとえそうであっても、変数は実際のタイプと実際の値を同時に持つことができます。 Stringobjectよりも制限型であるため、myCheckFuntion(Object a)を呼び出し

fn1 = new Function<object, DerivedClass>(pg.myCheckFuntion) 
fn2 = fn1; // here you copy the reference 

pg.myCheckFuntion("Hello");

2

fn2は、その宣言のmyCheckFuntion(Object a)を呼び出します。あなたはObjectに文字列にキャスト場合

pg.myCheckFuntion((object)"Hello"); 

をそれが他のメソッドを呼び出します。