委托的协变和逆变

  在 Framework 2.0 出现之前,委托协变这个概念还没有出现。此时因为委托是安全类型,它们不遵守继承的基础规则。即会这下面的情况:Manager 虽然是 Worker 的子类,但 GetWorkerHander 委托不能直接绑定 GetManager 方法,因为在委托当中它们的返回值 Manager 与 Worker 被视为完全无关的两个类型。

 1      public class Worker
 2      {.......}
 3      public class Manager:Worker
 4      {.......}
 5  
 6       class Program
 7      {
 8          public delegate Worker GetWorkerHandler(int id);
 9          public delegate Manager GetManagerHandler(int id);
10  
11          public static Worker GetWorker(int id)
12          {
13              Worker worker = new Worker();
14              ..............
15              return worker;
16          }
17  
18          public static Manager GetManager(int id)
19          {
20              Manager manager = new Manager();
21              ..............
22              return manager;
23          }
24  
25          static void Main(string[] args)
26          {
27              GetWorkerHandler workerHandler = new GetWorkerHandler(GetWorker);
28              var worker=workerHandler(1);
29  
30              GetManagerHandler managerHandler = new GetManagerHandler(GetManager);
31              var manager = managerHandler(2);
32              Console.ReadKey();
33          }
34      }

自从Framework 2.0 面试以后,委托协变的概念就应运而生,此时委托可以按照传统的继承规则进行转换。即 GetWorkerHandler 委托可以直接绑定 GetManager 方法。

 1      public class Worker
 2      {.......}
 3      public class Manager:Worker
 4      {.......}
 5  
 6       class Program
 7      {
 8          public delegate Worker GetWorkerHandler(int id);
 9          //在 Framework2.0 以上,委托 GetWorkerHandler 可绑定 GetWorker 与 GetManager 两个方法
10  
11          public static Worker GetWorker(int id)
12          {
13              Worker worker = new Worker();
14              return worker;
15          }
16  
17          public static Manager GetManager(int id)
18          {
19              Manager manager = new Manager();
20              return manager;
21          }
22  
23         static void Main(string[] args)
24         {
25             GetWorkerHandler workerHandler = new GetWorkerHandler(GetWorker);
26             Worker worker=workerHandler(1);
27             GetWorkerHandler managerHandler = new GetWorkerHandler(GetManager);
28             Manager manager = managerHandler(2) as Manager;
29             Console.ReadKey();
30         }
31      }

委托逆变,是指委托方法的参数同样可以接收 “继承” 这个传统规则。像下面的例子,以 object 为参数的委托,可以接受任何 object 子类的对象作为参数。最后可以在处理方法中使用 is 对输入数据的类型进行判断,分别处理对不同的类型的对象。

 1     class Program
 2     {
 3         public delegate void Handler(object obj);
 4 
 5         public static void GetMessage(object message)
 6         {
 7             if (message is string)
 8                 Console.WriteLine("His name is : " + message.ToString());
 9             if (message is int)
10                 Console.WriteLine("His age is : " + message.ToString());
11         }
12 
13         static void Main(string[] args)
14         {
15             Handler handler = new Handler(GetMessage);
16             handler(29);
17             Console.ReadKey();
18         }
19    }

运行结果

注意委托与其绑定方法的参数必须一至,即当 Handler 所输入的参数为 A 类型,其绑定方法 GetMessage 的参数也必须为 A 类或者 A 的父类 。相反,当绑定方法的参数为 A 的子类,系统也无法辨认。

来源:http://www.cnblogs.com/zhangyanhai/archive/2013/10/09/3359240.html

原文地址:https://www.cnblogs.com/xuekai-to-sharp/p/3368303.html