zoukankan      html  css  js  c++  java
  • C#2.0之细说泛型

    C#2的头号亮点 : 泛型

    C#1中,Arraylist总是会给人带来困扰,因为它的参数类型是Object,这就让开发者无法把握集合中都有哪些类型的数据。如果对string类型的数据进行算术操作那自然会报错,但是遺憾的是在編譯期不会给你任何的提示

    C#2中引入的泛型极其耀眼,甚至有些人会因为泛型而忽略C#2中其它新加入的特性

       

    回到上面的问题,ArrayList带来的不仅仅是上面那些困扰,Object是所有类型的基类,但是我们在开发中它幾乎不会有它的身影,因为它包容一切,但是我们需要使用int做算术操作的时候就发生了问题,就是强制类型转换。当我们需要使用stringsubString方法IDE也不会给你任何提示,因为它是Object类型。

       

    泛型带来的就是这样革命性的改变,允許你的参数类型为泛型类型。回到ArrayList,泛型的典型就是List<T>了,而T就是泛型类型,它是一个未綁定类型(不明确的)。但是在我们使用的时候需要进行指定

    List<string> strList = new List<string>();

    这时我们去访问它的元素时就会有string数据类型的智能提示,我们可以輕松的点出subString方法。这时 List<string>就是已构造 的泛型类型。而且因为是显示的,也不会有类型转换的问题。性能上也是大大的提高,这时我们把运行时需要检查的提前到了编译时

    开放封闭类型

    这是一个比较绕的概念,看名称比较迷糊其实很容易理解。

    泛型类型虽然也是类型,而T就是泛型类型,但它是开放的,可以是string,int,class等。开放类型无法创建实例,因为不知道创建什么实例,而封闭类型可以创建实例,封装类型就是指定了实际的数据类型,比如<string>

       

    泛型约束

    泛型类型也不总是任意数据类型都可以的,在开发的时候我们常常需要对传入的实际类型进行把握,如果外部使用时传入了意外的类型,那么就会引发BUG

    引用类型约束

    如果我们希望数据类型是引用类型,那么我们可以 where T: class

    值类型约束

    如果我们希望数据类型是值 类型,那么我们可以 where T: struct

    構造函數约束

    我们希望数据类型是拥有无参的构造函数,那么我们可以 where T: new()

    转换类型约束

    我们希望数据类型是可以转换为我们想要指定的数据类型,比如某个基类的子类,某个接口的实现。我们可以 where T: Person

    我们还可以根据实际需要进行组合约束,但是需要注意的是不是所有的约束都可以组合在一起,比如 约束不可以既是引用类型约束又是值类型约束。

       

    泛型方法类型实参的类型推断

    需要注意的是,这并不是我们常用的var类型推断,而是泛型方法的类型推断。

    比如list<string>.Add("小明"); 这时小明很明显是一个字符串,那么这段代码就可以简化成 list.Add("小明");

       

    高级泛型

    这部分主要讨论的是泛型的效率问题与反射部分

    都知道,相比较arrayList,泛型不会有拆箱装箱的过程,除了这些他们在内存中存儲的方式也是不一样的。比如ArrayListbyteList<byte>ArrayList会为每一个字节进行装箱并存儲已装箱值的引用。而List<byte>没有額外的引用存儲。他们看起来如下图

       

    对于静态类型与静态字段还有静态構造函數, 我们都知道他们只会初始化一次,并且之后不会发生改变。对于泛型来说同一个泛型参数类型确实如此 ,每个封闭类型都有自己的静态字段集。它们是独立的。

    比如 List<int> a;

    List<string> b;

    List<object > c;

    List<int> d;

    我们可以看到ad是一个泛型参数类型,它们是静态构造函數只会运行一次,但是bca会走三次,因为类型不一样。

       

    JIT编译器处理泛型的时候,会把值类型翻译成不同的本地码,而引用类型翻译成共享的本地码。因为引用具有相同的大小。而值类型并不是。

       

    我们在使用foreach的时候会感到很便利,有时候我们也会自己实现一个迭代器,这很简单,只要去实现IEnumerable<T>接口与IEnumerator<T>接口即可,但是如果我们发现泛型的接口又实现着非泛型的接口。如果没有问题,泛型接口都应该继承一个对应的非泛型接口,这样就可以实现协变性,在之前的C#版本中也会适用。

       

       

    泛型存在的不足

    C#的泛型设计的非常的巧妙,但是也有一些存在的不足之处。

       

    泛型可变性(协变、逆变)的缺乏

    在面向对象开发中我们可以用子类去New基类,这是没有问题的,但是对于泛型来说是不可以的,可以看到代码第一行是报错的。泛型不支持可变性,它们是不变体,这是为了类型安全着想

       

    但是我们可以通过其它方法来实现可变性。最简单的使用泛型接口,和编写輔助类。在4.0中有了其它的解决方法

       

    缺乏操作符约束

    我们想要对泛型实参进行算术运算,但是并不是所有的类型都可以进行算术运行的。也没有类似于 + - / *这种操作符的约束。我们可以使用表达式树和动态特性解决此问题

       

    缺乏泛型属性、索引器、成员类型

    这很直观 ,上面所说的都无法使用泛型,我们不可以

    Public T Property<T>{get;set;}

    当然这个是无解的。因为至少我们开发的时候不会有这样的需求

  • 相关阅读:
    大数乘法
    大数阶乘
    存js导入excel文件
    设计模式详解
    javascript的api设计原则
    从零开始nodejs系列文章
    git的学习
    如何暴力学英语
    Vsftpd
    shell命令学习
  • 原文地址:https://www.cnblogs.com/LiangSW/p/7168280.html
Copyright © 2011-2022 走看看