请考虑以下代码段
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();
}
}
为什么委托调用和普通方法调用调用不同的方法。
答案 0 :(得分:8)
委托在编译时绑定到myCheckFuntion(Object)
- 您告诉它找到接受Object
的方法。该绑定仅适用于单个方法 - 它不会根据实际参数类型在执行时执行重载解析。
当您致电pg.myCheckFuntion("Hello")
时,将在编译时绑定到myCheckFuntion(String)
,因为"Hello"
是一个字符串,并且首选从字符串到字符串的转换在重载决策中从字符串到对象的转换。
请注意,如果你写:
object text = "Hello";
pg.myCheckFuntion(text);
然后 将调用myCheckFuntion(Object)
。
答案 1 :(得分: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");
它将调用其他方法。
答案 2 :(得分:1)
委托对象本身仍然只指向一个函数,而不指向一系列函数。 co(ntra)方差仅允许您将其指向更大的函数类型域。同样,您可以将所有类型的值分配给object
类型的变量,但更少类型为string
的变量。即便如此,变量在任何给定时间仍然只有一个实际类型和一个实际值。