12 泛型

使用值类型作为参数的泛型容器,传入值类型的参数时,不需要进行装箱

12.1 FCL中的泛型

System.Array中提供了很多泛型方法

  1. AsReadOnly
  2. BinarySearch
  3. ConvertAll
  4. Exists
  5. Find
  6. FindAll
  7. FindIndex
  8. FindLast
  9. FindLastIndex
  10. ForEach
  11. IndexOf
  12. LastIndexOf
  13. Resize
  14. Sort
  15. TrueForAll

12.2 泛型基础结构

12.2.1 开放类型和封闭类型

  1. 具有泛型类型参数的类型成为开放类型

    1. CLR禁止构建开放类型的实例
  2. 为所有类型参数传递了具体类型,则成为封闭类型

    2. 使用不同参数创建的封闭类型,静态成员不同享

12.2.3 泛型类型的同一性

使用using关键字来创建一个类的别名

using DataList = List<Data>;
// 返回true
typeof(DataList) == typeof(List<Data>);

12.2.4 代码爆炸

  1. 使用引用类型的泛型类共享一份代码
  2. 使用值类型的泛型类由编译器生成独一份的代码

12.5 委托和接口的逆变和协变泛型类型实参

泛型委托

泛型委托的泛型类型可以标记为你变量和协变量,默认为不变量

  1. 不变量(invariant):默认,参数类型不可变
  2. 逆变量(contravariant):可以变为子类,只能作为输入
  3. 协变量(covariant):可以变为基类,只能作为输出
delegate TResult Func<in T, out TResult>(T arg);

Func<object, ArgumentException> fn1 = null;
// 可以赋值给另一种使用不同类型参数的泛型委托
Func<string, Exception> fn2 = fn1; // 这是错的
fn1 = fn2;

这也很好理解,Func<string, Exception>的参数和输出是兼容Func<object, ArgumentException>的,例如下面的程序展示的那样:

ArgumentException Func1(object arg) {
...
}
Exception Func2(string arg) {
return Func1(arg);
}

在Func2中调用Func1是OK的,参数可以隐式转化为其基类类型,而反过来则是不对的,不能隐式转为其子类类型。

泛型接口

泛型接口的类型参数也可以声明为逆变量或协变量

interface IWhatTheFuck<in T, out TResult> {
TResult Func(T arg);
} IWhatTheFuck<object, ArgumentException> if1 = null;
IWhatTheFuck<string, Exception> if2 = null; if2 = if1; // 通过编译
if1 = if2; // 编译失败

值类型

值类型作为模板参数时不能逆变或协变(涉及装箱和拆箱)。

12.6 泛型方法

如果普通方法和泛型方法同时匹配一个调用,编译器优先适配普通方法

12.7 泛型和其他成员

属性,索引器,事件,操作符方法,构造器,终结器本身不能有类型参数,但可以使用类的泛型参数

12.8 可验证性和约束

这样的函数无法通过编译

static T Min<T>(T o1, T o2) {
if (o1.CompareTo(o2) < 0) return o1;
return o2;
}

通过添加约束

static T Min<T>(T o1, T o2) where T : IComparable<T> {
if (o1.CompareTo(o2) < 0) return o1;
return o2;
}
  1. 通过泛型约束无法重载
  2. 通过参数个数可以重载
  3. 重写虚泛型方法时,所有的约束会继承,不能添加新的约束

主要约束

  1. 主要约束可以是除了这些类型之外的引用类型:

    1. Object
    2. Array
    3. Delegate
    4. MultiCastDelegate
    5. ValueType
    6. Enum
    7. Void
  2. 指定了主要类型之后,类型参数只能是主要类型或者其子类。
  3. 有两种特殊的主要约束:
    1. class:包括了class,interface,delegate,array
    2. struct:所有的值类型,包括了一个默认的无参数构造函数

次要约束

  1. 指明需要实现的多个接口
  2. 指明多个类型参数之间的关系
    static List<TBase> ConvertIList<T, TBase>(IList<T> list) where T : TBase {
    List<TBase> baseList = new List<TBase>(list.Count);
    for (int i = 0; i < list.Count; i++) {
    baseList.Add(list[i]);
    }
    }

构造函数约束

  1. 约束中可以包含一个构造器约束
  2. 指定类型可以有一个public,无参数的构造函数
  3. 主要约束为值类型,无需指定构造函数约束

其他情况

  1. 隐式转型模板函数中的未定类型变量是非法的,除非在约束中指定过了
  2. 使用defaut(T)来初始化一个未定类型的变量
    1. 为引用类型初始化为null
    2. 为值类型初始化内存为0
  3. 未定类型变量与null进行比较是否相等,编译器不会报错,如果是值类型作为参数,编译器判断为不等
    void func<T>(T o) {
    if (o == null) {
    // 如果T是引用类型,判断成立
    // 如果T是值类型,判断不成立
    // 但是编译器不会报错
    }
    }
  4. 相同类型的泛型类型变量之间不能直接比较是否相等
    void func<T>(T a, T b) {
    if (a == b) { ... } // 编译不通过
    if (EqualityComparer<T>.Default.Equals(a, b)) { ... } // 编译通过
    }
  5. 泛型类型变量无法作为操作数使用
    void func<T>(T a, T b) {
    var c = a + b; // 编译不通过
    }

总结

  1. C#的泛型比C++模板是更好的存在

    1. 通过各种约束,可以直接编译泛型函数\类
    2. 模板需要实例化,导致代码爆炸,各模块\编译单元的实例化模板类还不通用,需要
      1. template class std::vector<int>;显式实例化
      2. template class __declspec(dllexport) std::vector<int>;实例化导出实例化的模板类
      3. extern template class std::vector<int>;引用别处的实例化模板类
  2. C#函数是如何调用的?
    1. 如果像C++那样,直接绑定函数地址,那么对于不同参数的模板类,类型成员函数的参数地址是不同的,如何做到不同参数的模板共享一份代码的呢?
    2. 如果模板类没有源码,怎样用dll中的开放类(已经编译成IL),生成一个参数为值类型的封闭类呢?

.NET via C#笔记12——泛型的更多相关文章

  1. Ext.Net学习笔记12:Ext.Net GridPanel Filter用法

    Ext.Net学习笔记12:Ext.Net GridPanel Filter用法 Ext.Net GridPanel的用法在上一篇中已经介绍过,这篇笔记讲介绍Filter的用法. Filter是用来过 ...

  2. 《CLR via C#》读书笔记 之 泛型

    第十二章 泛型 2014-06-15 初始泛型 12.3 泛型基础结构 12.3.1 开放类型与封闭类型 12.3.2 泛型类型和继承 12.3.3 泛型类型同一性 12.3.4 代码爆炸 12.6 ...

  3. 机器学习实战 - 读书笔记(12) - 使用FP-growth算法来高效发现频繁项集

    前言 最近在看Peter Harrington写的"机器学习实战",这是我的学习心得,这次是第12章 - 使用FP-growth算法来高效发现频繁项集. 基本概念 FP-growt ...

  4. C#&java重学笔记(泛型)

    C#部分: 1.泛型的出现主要用于解决类.接口.委托.方法的通用性,通过定义泛型类.接口.委托.方法,可以让不同类型的数据使用相同运算规则处理数据,方便了开发. 2.利用System.Nullable ...

  5. TypeScript笔记[5]泛型+Dictionary 转

    TypeScript笔记[5]泛型   在C++.C#.Java等主流编程语言中,一般对泛型编程提供了支持.合理利用泛型,可以提高开发效率.提升代码质量. 例如在C++编程语言中,常常利用下面的结构表 ...

  6. SQL反模式学习笔记12 存储图片或其他多媒体大文件

    目标:存储图片或其他多媒体大文件 反模式:图片存储在数据库外的文件系统中,数据库表中存储文件的对应的路径和名称. 缺点:     1.文件不支持Delete操作.使用SQL语句删除一条记录时,对应的文 ...

  7. JAVA自学笔记12

    JAVA自学笔记12 1.Scanner 1)JDK5后用于获取用户的键盘输入 2)构造方法:public Scanner(InputStream source) 3)System.in 标准的输入流 ...

  8. golang学习笔记12 beego table name `xxx` repeat register, must be unique 错误问题

    golang学习笔记12 beego table name `xxx` repeat register, must be unique 错误问题 今天测试了重新建一个项目生成新的表,然后复制到旧的项目 ...

  9. Spring MVC 学习笔记12 —— SpringMVC+Hibernate开发(1)依赖包搭建

    Spring MVC 学习笔记12 -- SpringMVC+Hibernate开发(1)依赖包搭建 用Hibernate帮助建立SpringMVC与数据库之间的联系,通过配置DAO层,Service ...

随机推荐

  1. 三大JavaScript框架对比——AngularJS、BackboneJS和EmberJS

    <三大JavaScript框架对比——AngularJS.BackboneJS和EmberJS> 本文转载自  作者:chszs,博客主页:http://blog.csdn.net/chs ...

  2. [POI 2014]PTA-Little Bird

    Description 题库连接 给你 \(n\) 棵树,第 \(i\) 棵树的高度为 \(d_i\).有一只鸟从 1 号树出发,每次飞跃不能超过 \(k\) 的距离.若飞到下一棵树的高度大于等于这一 ...

  3. 《容器化.NET应用架构指南》脑图学习笔记(第一部分)

    一.关于这本官方“圣经” 作为.NET程序员,对于微软官方推动的架构示例总是特别关注,从PetShop到MusicStore再到eShopOnContainers,每一次关注,都会了解到业界最新的架构 ...

  4. 随机游走模型(Random Walk)

    给定了一个时间顺序向量\(z_1,...,z_T\),rw模型是由次序r来定义的,\(z_t\)仅取决于前\(t-r\)个元素.当r = 1时为最简单的RW模型. 给定了向量的其他元素,\(z_t\) ...

  5. mysql 命令行个性化设置

    通过配置显示主机和用户名 mysql -u root -p --prompt="(\u@\h) [\d]>" 或在配置文件中修改,可在命令行中的目标位置查看 --tee na ...

  6. Python连载60-Tkinter布局、按钮以及属性详解

    一.Tkinter​ 1.组件的大致使用步骤 (1)创建总面板 (2)创建面板上的各种组件: i.指定组件的父组件,即依附关系:ii.利用相应的属性对组件进行设置:iii.给组件安排布局. (3)同步 ...

  7. 防火墙问题 Linux系统 /etc/sysconfig/路径下无iptables文件

    虚拟机新装了一个CentOs7,然后做防火墙配置的时候找不到iptables文件,解决方法如下: 因为默认使用的是firewall作为防火墙,把他停掉装个iptable systemctl stop ...

  8. 解决css中display:inline-block产生的空隙问题

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. sql语句中,传入的参数带单引号的问题

    今天在大批量操作数据时,遇到此问题,解决如下: if(cateName.indexOf("'")!=-1){ oql = " select * where name = ...

  10. [*CTF2019]babyflash

    用JPEXS反编译flash.swf得到441张黑白图片和1个mp3文件 软件下载地址:https://github.com/jindrapetrik/jpexs-decompiler/release ...