2011-07-22 53 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"); 

它会调用其他方法。