2011-07-22 52 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的方法。該綁定僅適用於單個方法 - 它不會根據實際參數類型在執行時執行重載解析。

當調用pg.myCheckFuntion("Hello")將結合myCheckFuntion(String)在編譯時間,因爲"Hello"是一個字符串,並從字符串到字符串轉換優於從字符串轉換在重載解析到對象。

請注意,如果你寫:

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

然後將調用myCheckFuntion(Object)

+0

沒有什麼可添加的。 +1 –

+0

你無法擊敗Jon Skeet! – siride

+0

對我來說太快了:( – VMAtm

1

委託對象本身仍然只指向一個函數,而不是指向一系列函數。 co(ntra)方差僅允許您將其指向函數類型的更大範圍。以同樣的方式,您可以將所有類型的值分配給類型爲object的變量,但對於類型爲string的變量分配的值更少。即使如此,變量在任何給定時間仍然只有一個實際類型和一個實際值。

2

fn2調用myCheckFuntion(Object a)因其聲明:

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

pg.myCheckFuntion("Hello");調用myCheckFuntion(Object a)因爲String是更嚴格的類型比object

如果你投字符串Object

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

它會調用其他方法。