在上面的几篇文章中,我们介绍了有关数组的 Variance、接口和委托的 Covariance 的概念和基本用法。本文介绍在 Variance 上的另外一种情况,即 Contra-variance。

Contra-variance 是一种将泛型类型从大到小转换的场景。 有些时候对于一个泛型委托,我们常常需要对其类型参数 T 进行引用转换,以便于实现 Composite 或者 Facade 模式。设 D<T1> 和 D<T2> 是两个泛型委托 D<> 的实例,T1 和 T2 具备继承关系,并且 T1 < T2,则如果允许 D<T2> 隐含转换为 D<T1>,则称为 D<> 支持 Cotra-variance。

支持 Contra-variance 的泛型类型可以表示为 X<in T> 或者 X<T->,其中 X 是接口或者是委托。

一个简单的例子

这个实例说明如何利用委托处理根据学生对象类别来选择执行存储数据的场景。请参考下面的代码。

  1: using System;
  2: using System.Collections.Generic;
  3: using System.Linq;
  4: using System.Text;
  5:
  6: namespace Demo
  7: {
  8:     class Program
  9:     {
 10:         static void Main(string[] args)
 11:         {
 12:             PrimaryStudent s1 = new PrimaryStudent();
 13:             JuniorStudent s2 = new JuniorStudent();
 14:             SeniorStudent s3 = new SeniorStudent();
 15:
 16:             // Define the generic save handler.
 17:             SaveFunc<Student> saveFunc = s => Console.WriteLine(s.Type);
 18:
 19:             // Set save delegates.
 20:             StudentDataStore<Student> dataStore1 = new StudentDataStore<Student>();
 21:             dataStore1.SaveHandler = saveFunc;
 22:             dataStore1.Save(s1);
 23:
 24:             StudentDataStore<JuniorStudent> dataStore2 = new StudentDataStore<JuniorStudent>();
 25:             // Contra-variance.
 26:             dataStore2.SaveHandler = saveFunc;
 27:             dataStore2.Save(s2);
 28:
 29:             // No variance.
 30:             dataStore2.Save((JuniorStudent)(Student)s3);
 31:         }
 32:     }
 33:
 34:     enum StudentType
 35:     {
 36:         Primary,
 37:         JuniorHigh,
 38:         SeniorHigh,
 39:         College,
 40:         Unknown
 41:     }
 42:
 43:     delegate void SaveFunc<in T>(T student) where T : Student;
 44:
 45:     class StudentDataStore<T> where T : Student
 46:     {
 47:         public virtual void Save(T student)
 48:         {
 49:             if (SaveHandler != null)
 50:             {
 51:                 SaveHandler(student);
 52:             }
 53:         }
 54:         public SaveFunc<T> SaveHandler { get; set; }
 55:     }
 56:
 57:     class Student
 58:     {
 59:         public Guid Id { get; set; }
 60:         public string Name { get; set; }
 61:         public string ControlNumber { get; set; }
 62:         public virtual StudentType Type { get; set; }
 63:     }
 64:
 65:     class PrimaryStudent : Student
 66:     {
 67:         public override StudentType Type
 68:         {
 69:             get
 70:             {
 71:                 return StudentType.Primary;
 72:             }
 73:         }
 74:     }
 75:
 76:     class JuniorStudent : Student
 77:     {
 78:         public override StudentType Type
 79:         {
 80:             get
 81:             {
 82:                 return StudentType.JuniorHigh;
 83:             }
 84:         }
 85:     }
 86:
 87:     class SeniorStudent : Student
 88:     {
 89:         public override StudentType Type
 90:         {
 91:             get
 92:             {
 93:                 return StudentType.SeniorHigh;
 94:             }
 95:         }
 96:     }
 97: }
 98: 

程序首先创建了三个 Student 的实例 s1, s2 和 s3,然后针对于不同的 Student 类型声明了两个 StudentDataStore,并将 SaveHandler 初始化为已经声明好的一个泛型委托的实例 saveFunc。注意,saveFunc 的类型为 SaveFunc<Student>,由于该类型被声明为 SaveFunc<in T>,支持 Contra-variance(47 行)。s1.SaveHandler 类型为 SaveFunc<Student>,与赋值的右值类型相同。因此,对 s1.SavezHandler 的赋值有效(21 行)。

我们再来看看对于 s2.SaveHandler 的赋值(26 行 )。s2.SaveHandler 的类型为 SaveFunc<JuniorStudent>,saveFunc 的类型仍旧未 SaveFunc<Student>,这里产生了 Contra-variance,从大类型 SaveFunc<Student> 转换为小类型 SaveFunc<JuniorStudent>。

最后看看 s3,s3 类型为 SeniorStudent,而 dataStore2.Save() 方法需要一个 JuniorStudent 类型的参数,因此必须对 s3 进行强制引用转换才能达到目的。这里没有 Contra-variance。

总结

Contra-variance 往往在泛型委托上使用,它能很好的解决一些常用设计模式中需要解决的问题,更大程度上提高了泛型的应用宽度和价值。到目前为止,我们的关于 Variance 特性的介绍就告一段落了,如果大家还有什么更深的问题,欢迎来信交流。下一篇文章我们将介绍 C#  4.0 中的命名和可选参数。

C# 4.0 新特性 -- Contra-Variance相关推荐

  1. JDK5.0新特性系列---目录

    JDK5.0新特性系列---目录 JDK5.0新特性系列---1.自动装箱和拆箱 JDK5.0新特性系列---2.新的for循环 JDK5.0新特性系列---3.枚举类型 JDK5.0新特性系列--- ...

  2. [转]C# 2.0新特性与C# 3.5新特性

    C# 2.0新特性与C# 3.5新特性 一.C# 2.0 新特性: 1.泛型List<MyObject> obj_list=new List(); obj_list.Add(new MyO ...

  3. Servlet 3.0 新特性概述

    Servlet 3.0 新特性概述 Servlet 3.0 作为 Java EE 6 规范体系中一员,随着 Java EE 6 规范一起发布.该版本在前一版本(Servlet 2.5)的基础上提供了若 ...

  4. Redis 6.0 新特性-多线程连环13问!

    来自:码大叔 导读:支持多线程的Redis6.0版本于2020-05-02终于发布了,为什么Redis忽然要支持多线程?如何开启多线程?开启后性能提升效果如何?线程数量该如何设置?开启多线程后会不会有 ...

  5. WCF4.0新特性体验(3):标准终结点(Standard Endpoints)

    今天在WCF4.0新特性体验第3节,我们介绍WCF4.0里的标准终结点概念,也就是Standard Endpoints. WCF4.0提供了那些标准终结点?他们有什么作用?如何使用标准终结点?如何该表 ...

  6. Servlet 2.0 Servlet 3.0 新特性

    概念:透传. Callback 在异步线程中是如何使用的.?? Servlet 2.0 && Servlet 3.0 新特性 Servlet 2.0 && Servle ...

  7. C#6.0,C#7.0新特性

    C#6.0,C#7.0新特性 C#6.0新特性 Auto-Property enhancements(自动属性增强) Read-only auto-properties (真正的只读属性) Auto- ...

  8. WCF4.0新特性体验(6):路由服务Routing Service(下)

    紧接前文WCF4.0新特性体验(5):路由服务Routing Service(上).今天我们介绍WCF4.0消息路由的实现机制,然后会讲解路由服务的实现过程. [4]WCF与路由服务: 其实在介绍WC ...

  9. 【收藏】C# 2.03.0新特性总结

    c#2.0新特性 范型 我们知道通用的数据结构可以采用object存储任何数据类型.使用object问题是: 显示的强制转带来的代码复杂性 换装箱拆箱的性能损失(为什么有性能损失?因为涉及动态内存分配 ...

  10. 返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 Web API

    返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 Web API 原文:返璞归真 asp.net mvc (10) - asp.net mvc 4.0 新特性之 ...

最新文章

  1. 102. Binary Tree Level Order Traversal
  2. 康奈尔大学对博士生的四点要求
  3. java k线绘制,用Java绘制K线图[Java编程]
  4. mysql备份到带库_RMAN备份恢复——备份到带库的性能
  5. 论文拒稿的评价可以有多狠?
  6. 车辆动力学及控制_第一届国际轮胎动力学仿真技术峰会在长春举行
  7. mysql都有什么基本函数_【第七章】MySQL的基本函数
  8. 一种非常好用的图像处理软件
  9. 将log4j重定向到指定函数
  10. Android自适应国际化语言
  11. html5广告拦截器识别代码做提示(本站内容无法显示)
  12. javascript 操作coolie
  13. 【MMML】多模态机器学习高被引综述论文笔记
  14. RFID技术实现汽车零部件与EDI自动连接
  15. 计算机硕士研究生论文格式,计算机硕士论文格式
  16. 程序员快速成长的核心原则
  17. 读OpenSceneGraph快速入门指导(Paul Martz著王锐钱学雷译)有感
  18. Moderate Modular Mode
  19. C语言 编写函数求n个整数的和
  20. c语言程序设计教程博客,嵌入式C语言教程以及C编程要素

热门文章

  1. 关于Web软件的界面设计——《Web软件用户界面设计指南》
  2. 2030年人类将与人工智能结合 变身“混血儿”
  3. ​ICLR 2023 | 表达力 v.s. 泛化性:我们真的需要更强大的GNN吗?
  4. 力姆泰克IMB系列伺服电动缸
  5. 大多数金融服务都将开放,通过API无缝集成到SaaS
  6. [CIamp;CD]jenkins自动化工具使用教程
  7. 乐天移动和NEC开始生产Open RAN 5G无线设备
  8. 现代企业文化杂志现代企业文化杂志社现代企业文化编辑部2023年第1期目录
  9. 小学三年计算机教案,小学信息技术教案三年级
  10. 在家怎么连接学校电脑的相关部署?