委托协变和逆变

7
考虑以下代码片段:
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();
    }
 }

为什么委托调用和普通方法调用调用不同的方法。
3个回答

8
委托在编译时绑定到myCheckFuntion(Object) - 您正在告诉它查找一个接受Object的方法。这个绑定只是针对单个方法 - 它不会根据实际参数类型执行重载决议。
当您调用pg.myCheckFuntion("Hello")时,将绑定到myCheckFuntion(String),因为"Hello"是一个字符串,在重载决议中,从字符串到字符串的转换优先于从字符串到对象的转换。
请注意,如果您编写:
object text = "Hello";
pg.myCheckFuntion(text);

那么 那个 会调用 myCheckFuntion(Object)

没有什么可补充的了。+1 - Ivan Danilov
@siride:是的,我通过尝试才发现了它的困难。 - Ivan Danilov

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

它会调用其他方法。


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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接