C#2.0之细说泛型
C#2的头号亮点 : 泛型
在C#1中,Arraylist总是会给人带来困扰,因为它的参数类型是Object,这就让开发者无法把握集合中都有哪些类型的数据。如果对string类型的数据进行算术操作那自然会报错,但是遺憾的是在編譯期不会给你任何的提示
C#2中引入的泛型极其耀眼,甚至有些人会因为泛型而忽略C#2中其它新加入的特性
回到上面的问题,ArrayList带来的不仅仅是上面那些困扰,Object是所有类型的基类,但是我们在开发中它幾乎不会有它的身影,因为它包容一切,但是我们需要使用int做算术操作的时候就发生了问题,就是强制类型转换。当我们需要使用string的subString方法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,泛型不会有拆箱装箱的过程,除了这些他们在内存中存儲的方式也是不一样的。比如ArrayList的byte和List<byte>。ArrayList会为每一个字节进行装箱并存儲已装箱值的引用。而List<byte>没有額外的引用存儲。他们看起来如下图
对于静态类型与静态字段还有静态構造函數, 我们都知道他们只会初始化一次,并且之后不会发生改变。对于泛型来说同一个泛型参数类型确实如此 ,每个封闭类型都有自己的静态字段集。它们是独立的。
比如 List<int> a;
List<string> b;
List<object > c;
List<int> d;
我们可以看到a与d是一个泛型参数类型,它们是静态构造函數只会运行一次,但是b、c、a会走三次,因为类型不一样。
JIT编译器处理泛型的时候,会把值类型翻译成不同的本地码,而引用类型翻译成共享的本地码。因为引用具有相同的大小。而值类型并不是。
我们在使用foreach的时候会感到很便利,有时候我们也会自己实现一个迭代器,这很简单,只要去实现IEnumerable<T>接口与IEnumerator<T>接口即可,但是如果我们发现泛型的接口又实现着非泛型的接口。如果没有问题,泛型接口都应该继承一个对应的非泛型接口,这样就可以实现协变性,在之前的C#版本中也会适用。
泛型存在的不足
C#的泛型设计的非常的巧妙,但是也有一些存在的不足之处。
泛型可变性(协变、逆变)的缺乏
在面向对象开发中我们可以用子类去New基类,这是没有问题的,但是对于泛型来说是不可以的,可以看到代码第一行是报错的。泛型不支持可变性,它们是不变体,这是为了类型安全着想
但是我们可以通过其它方法来实现可变性。最简单的使用泛型接口,和编写輔助类。在4.0中有了其它的解决方法
缺乏操作符约束
我们想要对泛型实参进行算术运算,但是并不是所有的类型都可以进行算术运行的。也没有类似于 + - / *这种操作符的约束。我们可以使用表达式树和动态特性解决此问题
缺乏泛型属性、索引器、成员类型
这很直观 ,上面所说的都无法使用泛型,我们不可以
Public T Property<T>{get;set;}
当然这个是无解的。因为至少我们开发的时候不会有这样的需求
C#2.0之细说泛型的更多相关文章
- 【C#复习总结】细说泛型委托
1 前言 本系列会将[委托] [匿名方法][Lambda表达式] [泛型委托] [表达式树] [事件]等基础知识总结一下.(本人小白一枚,有错误的地方希望大佬指正) 系类1:细说委托 系类2:细说匿名 ...
- .NET 4.0中的泛型协变和反变
转自:http://www.cnblogs.com/Ninputer/archive/2008/11/22/generic_covariant.html 随Visual Studio 2010 CTP ...
- .NET 4.0中的泛型协变和逆变
随Visual Studio 2010 CTP亮相的C#4和VB10,虽然在支持语言新特性方面走了相当不一样的两条路:C#着重增加后期绑定和与动态语言相容的若干特性,VB10着重简化语言和提高抽象能力 ...
- .NET 4.0中的泛型逆变和协变
转载自:http://www.cnblogs.com/Ninputer/archive/2008/11/22/generic_covariant.html:自己加了一些理解 随Visual Studi ...
- Spring框架入门之Spring4.0新特性——泛型注入
Spring框架入门之Spring4.0新特性——泛型注入 一.为了更加快捷的开发,为了更少的配置,特别是针对 Web 环境的开发,从 Spring 4.0 之后,Spring 引入了 泛型依赖注入. ...
- .NET 4.0中的泛型的协变和逆变
转自:http://www.cnblogs.com/jingzhongliumei/archive/2012/07/02/2573149.html 先做点准备工作,定义两个类:Animal类和其子类D ...
- 转载.NET 4.0中的泛型的协变和逆变
先做点准备工作,定义两个类:Animal类和其子类Dog类,一个泛型接口IMyInterface<T>, 他们的定义如下: public class Animal { } public ...
- Spring4.0开始的泛型依赖
参考资料: http://www.cnblogs.com/solverpeng/p/5687304.html 视频地址:https://edu.51cto.com/course/1956.html 一 ...
- 【C#复习总结】细说表达式树
1 前言 系类1:细说委托 系类2:细说匿名方法 系列3:细说Lambda表达式 系列4:细说泛型委托 系列5:细说表达式树 系列6:细说事件 涛声依旧,再续前言,接着用大佬的文章作为开头. 表达式树 ...
随机推荐
- 关于JQ中,新生成的节点on绑定事件失效的解决
老旧的JQ库在做新生成DIV的click事件绑定,需要先绑定其现有的父元素,在追踪到需要事件绑定的子节点上 如以下这段代码$(".t_in").on("click&quo ...
- lua 文件编译相关工具
-- 编译一个代码文件 -- loadfile (lua_State *L, const char *filename); -- 将一个文件加载为lua代码块,仅编译不执行,返回值为编译后的 -- 代 ...
- CF1097G Vladislav and a Great Legend
传送门 题目大意 一棵$n$个点的树,一个点集$S$的权值定义为把这个点击连成一个联通块的最少边数,求: $$ans=\sum_{S\in U}f(S)^k$$ 题解 这题跟gdoi那道题差不多 先把 ...
- System.InvalidOperationException: 支持“XXX”上下文的模型已在数据库创建后发生更改。请考虑使用 Code First 迁移更新数据库(http://go.microsoft.com/fwlink/?LinkId=238269)。
System.InvalidOperationException: 支持“XXX”上下文的模型已在数据库创建后发生更改.请考虑使用 Code First 迁移更新数据库(http://go.micro ...
- MyBatis返回map数据
(1)接口中编写方法 //单行 public Map<String, Object> getEmpReturnMap(Integer id); //多行 @MapKey("id& ...
- fildder
来自 墨痕 :https://home.cnblogs.com/u/ink-marks/ FIDDLER的使用方法及技巧总结 一.FIDDLER快速入门及使用场景 Fiddler的官方网站:htt ...
- Win 10 Revit 2019 安装过程,亲自踩的一遍坑,有你想要的细节
首先就是安装吖,不管是管理员权限还是普通权限,都是以下这个问题,跟权限没关系 failed to load .....revitcontentpackui.dll (126) 尝试了网上能查到的各种方 ...
- Vue(二十七)当前GitHub上排名前十的热门Vue项目(转载)
原文地址:https://my.oschina.net/liuyuantao/blog/1510726 1. ElemeFE/element tag:vue javascript components ...
- c++ 读取不了hdf5文件中的字符串
问题描述: 在拿到一个hdf5文件,想用c++去读取文件中的字符串,但是会报错:read failed ps: c++读取hdf5的字符串方法见:https://support.hdfgroup.or ...
- Winsock编程基础2(UDP流程)
UDP用户数据报协议 服务器端 <1 创建套接字(socket) <2 绑定IP地址和端口(bind) <3 收发数据(sendto, recvfrom) <4 关闭连接(cl ...