考虑以下代码片段
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
的变量分配的值较少。即便如此,在任何给定时间,变量仍然只有一个实际类型和一个实际值。