委托协方差和协方差



考虑以下代码片段

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();
    }
 }

为什么委托调用和普通方法调用调用不同的方法

委托在编译时绑定到myCheckFuntion(Object) -你告诉它找到一个接受Object的方法。该绑定仅针对单个方法——它不会在执行时根据实际参数类型执行重载解析。

当你调用pg.myCheckFuntion("Hello") 时,将在编译时绑定到myCheckFuntion(String),因为"Hello"是一个字符串,并且从字符串到字符串的转换优先于从字符串到对象的转换。

注意如果你写:

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

then that将调用myCheckFuntion(Object)

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");

它将调用其他方法

委托对象本身仍然只指向一个函数,而不是指向一系列函数。co(ntra)方差只允许您将其指向更大的函数类型域。以同样的方式,您可以为类型为object的变量分配各种值,但为类型为string的变量分配的值较少。即便如此,在任何给定时间,变量仍然只有一个实际类型和一个实际值。

最新更新