【Clr in c#】泛型
使用泛型的好处是“代码重用”,极大的提高了开发效率,泛型为开发者提供了以下优势:
1,源代码保护 算法的源代码不需要提供给使用泛型算法的开发人员,使用c++模板的泛型技术需要提供。(目前c++模板的泛型技术了解较少)
2,类型安全 给泛型算法指定类型时,编译器能理解开发者意图,只有兼容类型能通过,不兼容的时候编译时候会报错。
3,更清晰的代码 由于编译器强制类型的安全性,减少源代码中必须进行的转型次数,使得代码容易维护和编写。例如:DateTime dt=dtList[0];从DateTime的集合中按照索引取出来的值可以直接赋值给DateTime类型,不需要转型。
4,更佳的性能 在操作值类型时候,非泛型集合会造成装箱、拆箱操作,会造成托管堆上的内存分配,会造成频繁的垃圾回收,影响性能。
补充:对于泛型方法,约束父类类型,与参数直接传递父类,在没有返回值的情况下是没有区别的,假如有需要返回传入的类型,则用泛型方法比较合适,因为通过泛型方法返回的类型不需要经过类型转换 http://bbs.csdn.net/topics/380050195
public class AA{}
public class BB:AA{} public void GetText<T>(T t) where T:AA
{
}
与
public void GetText(AA x)
{}之间是等效的,没有区别。 public T GetText<T>(T t) where T:AA
{
}
public AA GetText(AA x)
在调用的地方是有区别的 BB b=new BB();
var rtGetText=GetText<BB>(b);
var rtGetText2=(BB)GetText(B);//需要进行一次类型转换
1.泛型基础结构
1.1 开放类型和封闭类型
具有泛型类型参数的类型称为开放类型。
不能创建实例。例如Dictionary<,>,没有指定参数,目前尚不清楚这个开放类型有什么用。
所有类型实参传递的都是实际数据类型为封闭类型。
使用约束无法将类型实参限制为某一类型,可以用一个静态构造器来保证类型。如下
internal sealed class GenericTypeThatRequiresAnEnum<T>{
static GenericTypeThatRequiresAnEnum(){
if(!typeof(T).IsEnum){
throw new ArgumentException("T must be an enumerated type");
}
}
}
1.2泛型类型的继承
泛型类型仍然是类型,它能从其他任何类型派生。
public class Node1<T>
{
public T m_data;
public Node1<T> m_next;
public Node1(T data) : this(data, null) { }
public Node1(T data, Node1<T> next)
{
m_data = data;
m_next = next;
}
public override string ToString()
{
// ABC
return m_data.ToString()+((m_next!=null)?m_next.ToString():null);
}
}
上面例子必须是相同数据类型下使用,加入链表需要多个m_data为多种类型的时候这种结构将无法满足,这时候我们可以考虑抽出一个非泛型的基类,这样继承的泛型就可以指定多种类型。这是一个泛型应用的技巧。
public class Node2
{
protected Node2 m_next; public Node2(Node2 next)
{
m_next = next;
}
} public class TypeNode<T> : Node2 {
public T m_data;
public TypeNode(T data,Node2 next):base(next){
m_data = data;
}
public TypeNode(T data):this(data,null){
}
public override string ToString()
{
// Tody is 时间。
return m_data.ToString() + ((m_next != null) ? m_next.ToString() : null);
}
}
1.3泛型类型的同一性
这种性质不经常用,这里简单记一下只当了解。
简化泛型的写法多封装一层去除"<"">"。
class DateTimeList:List<DateTime>{
//这里不需要放入任何代码。
}
这样使用的时候就没有<,>符号了。
DateTimeList dt=new DateTimeList();
这只是表面方便了,绝对不要单纯出于增强代码可读性目的定义一个新类,事实上也不会这么做,但是这样写会丧失同一性和相等性,如下代码为Flase
Boolean sameType=(typeof(List<DateTime>)==typeof(DateTimeList));
可以通过使用using指令弥补相等性,添加如下结果为True;
using DateTimeList=System.Collections.Generic.List<System.DateTime>;
1.4代码爆炸
使用泛型类型参数的一个方法在JIT(即时编译)编译时,Clr获取方法的IL,用指定的实参进行替换,创建恰当的本地代码,缺点是CLR要为每种不同的方法、类型组合生成本地代码,可能造成应用程序集显著增大,损坏性能,称之为 代码爆炸。
但是CRL内建了一些优化措施,缓解代码爆炸。所有程序集使用List<DateTime>时候,只会生成一次,认为所有引用类型实参都是完全相同,List<String>和List<Stream>可以公用,之所以会这样,是因为所有引用类型的实参或者变量实际都是指向堆上的对象指针,而指针全部都是以相同的方式来操作。
2,泛型接口
泛型接口的一个例子是IComparable接口,在接口里详细写
3,泛型委托
建议使用泛型的Action和Func委托,会在以后的委托中细说
4,委托和接口的逆变和协变泛型类型实参
不变量(invariant)表示泛型类型不可变。
逆变量(contravariant)表示泛型类型参数可以从一个基类更改为该类的派生类,用in关键字标记,只出现在输入位置。
协变量(covariant) 表示泛型类型可以从一个派生类更改为它的基类型,用out关键字标记,只出现在输出位置。
public delegate TResult Func<in T,out TResult>(T arg);
Func<object,ArgumentException> fn1=null;
func<string,Exception> fn2=fn1;//这里不需要显示转换,因为逆变量,协变量
调用委托Exception e=fn2("");
使用要获取泛型参数和返回值的委托时,建议尽量使用in和out关键字,因为不会有不良反应。
泛型接口和泛型委托一样也可以用out和in。
5,泛型方法
用一个例子介绍下泛型的定义,下面一个类型定义了一个类型参数,一个方法定义了它自己的专用类型参数。
class GenericType<T>{
private T m_value;
public GenericType(T value){m_value=value;}
public TOutput Coverter(TOutput)(){
TOutput result=(TOutput)Convert.ChangeType(m_value,typeof(TOutput ));
return result;
}
}
下面写一个比较经典常用的泛型方法,2个参数互换
private static void Swap<T>(ref T o1,ref T o2){
T temp=o1;
o1=o2;
o2=temp;
}
6泛型约束
确保使用当前泛型是自己想要的类型。
例如如下方法,在类型没有提供CompareTo方法时候会报错。
private static T Min<T>(T o1,To2){
if(o1.CompareTo(o2)<0)
return o1;
return o2;
}
这个时候我们就需要在该泛型方法添加泛型约束。
private static T Min<T>(T o1,To2) where T:IComparable<T>{
if(o1.CompareTo(o2)<0)
return o1;
return o2;
}
泛型约束主要分为3种。
1,主要约束 主要约束可以是一个引用类型,实参必须与约束相同或者派生,
例如where T:Stream ,使用该泛型方法必须是Stream 类型或者其派生类型。
where T:Class,使用该泛型方法必须是引用类型。
2,次要约束 次要约束代表的是一个借口类型,指定的参数必须实现所有接口约束例如 where T:IComparable<T>
3,构造器约束 指定的实参必须实现公共无参构造器的一个非抽象类型where T:New()
下面是项目中用到的一个泛型方法,模板反序列化。使用了Newtonsoft.Json
public T GetTemplateData<T>() where T : TemplateData
{
if (!string.IsNullOrEmpty(TemplateDataJsonStr))
{
T obj = (T)JsonConvert.DeserializeObject(TemplateDataJsonStr, typeof(T));
obj.CheckField();
return obj;
}
else return null; }
public void SetTemplateData(TemplateData templateData)
{
TemplateDataJsonStr= JsonConvert.SerializeObject(templateData);
}
【Clr in c#】泛型的更多相关文章
- clr via c# 泛型
1,类型对象,对于应用程序的各种类型创建的对象叫做类型对象:Type object:对于泛型类型参数的类型,CLR同样也会创建内部类型对象,适用于 引用类型 值类型 接口类型 委托类型 具有泛型类型参 ...
- CLR VIA C# 泛型的协变和逆变
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- CLR via C#深解笔记六 - 泛型
面向对象编程一个好处就是“代码重用”,极大提高了开发效率.如是,可以派生出一个类,让它继承基类的所有能力,派生类只需要重写虚方法,或添加一些新的方法,就可以定制派生类的行为,使之满足开发人员的需求. ...
- [CLR via C#]12. 泛型
泛型(generic)是CLR和编程语言提供一种特殊机制,它支持另一种形式的代码重用,即"算法重用". 简单地说,开发人员先定义好一个算法,比如排序.搜索.交换等.但是定义算法的开 ...
- CLR类型设计之泛型(一)
在讨论泛型之前,我们先讨论一下在没有泛型的世界里,如果我们想要创建一个独立于被包含类型的类和方法,我们需要定义objece类型,但是使用object就要面对装箱和拆箱的操作,装箱和拆箱会很损耗性能,我 ...
- CLR via C#关于泛型(Generics )的摘录
泛型,是CLR和编程语言提供的一种特殊机制,它支持另一种形式的代码重用,即“算法重用”. 简单的说,开发人员先定义好一个算法,比如排序.搜索.交换.比较或者转换等.但是,定义算法的开发人员并不设改算法 ...
- 《CLR via C#》读书笔记 之 泛型
第十二章 泛型 2014-06-15 初始泛型 12.3 泛型基础结构 12.3.1 开放类型与封闭类型 12.3.2 泛型类型和继承 12.3.3 泛型类型同一性 12.3.4 代码爆炸 12.6 ...
- 重温CLR(八 ) 泛型
熟悉面向对象编程的开发人员都深谙面向对象的好处,其中一个好处是代码重用,它极大提高了开发效率.也就是说,可以派生出一个类,让他继承基类的所有能力.派生类只需要重写虚方法,或添加一些新方法,就可定制派生 ...
- 泛型(Generics)
Framework类库中的泛型 泛型可以使代码重用,提高开发效率 CLR允许在引用类型.值类型或接口中定义泛型方法: CLR允许创建泛型引用类型.泛型值类型(枚举不允许创建).泛型委托类型和泛型接口类 ...
- CLR总览
Contents 第1章CLR的执行模型... 4 1.1将源代码编译成托管代码模块... 4 1.2 将托管模块合并成程序集... 6 1.3加载公共语言运行时... 7 1.4执行程序集的代码.. ...
随机推荐
- 【mongo】Can't take a write lock while out of disk space错误
今天遇到了这个错误,各种无法操作.找了很久的方案,都没用.最终发现,原来是我虚拟机硬盘满了......清除了些没用的东西,就恢复了.
- 9.27js拓展、bootstrap菜鸟教程
js(点击挂上 与 点击移除) <div id="dd" style="width:200px; height:200px; background-color:#6 ...
- ASP.Net后台 实现先弹出对话框,再跳转到另一个网页的实现方法
解决办法如下: Response.Write("<script>alert('想在对话框中显示的内容');window.navigate(‘要转到的页面的URL’)</sc ...
- xmpp xml基本语义
基本语义 9.2.1 消息语义 <message/>节种类可被看作“推”机制,一个实体推信息给其它实体,与 EMAIL 系统中发生的通信类似.所有消息节应该拥有‘to’ 属性,指定有意的消 ...
- [Android Pro] CPU占用计算方法
1: AVTest CPU计算方法读取每个进程的 stat 文件 (/proc/<PID>/stat)计算采样间隔10min下utime的差值minusUtime,stime的差值min ...
- top
. h或者? 显示帮助画面,给出一些简短的命令总结说明. k 终止一个进程.系统将提示用户输入需要终止的进程PID,以及需要发送给该进程什么样的信号.一般的终止进程可以使用15信号:如果不能正常结束那 ...
- codevs 1080 线段树练习
链接:http://codevs.cn/problem/1080/ 先用树状数组水一发,再用线段树水一发 树状数组代码:84ms #include<cstdio> #include< ...
- 给UILabel设置不同的字体和颜色
NSMutableAttributedString *str = [[NSMutableAttributedString alloc] initWithString:@"Using NSAt ...
- 360极速浏览器安装.crx扩展(postman)
用户在开发或者调试网络程序或者是网页B/S模式的程序的时候是需要一些方法来跟踪网页请求的,用户可以使用一些网络的监视工具比如著名的Firebug等网页调试工具.今天给大家介绍的这款网页调试工具不仅可以 ...
- javascript 面向对象编程小记
虽然平常用jquery用的很熟,但是基本都是面向过程的写法.一个事件一个function,很少有面向对象的写法.今天得写一个日期控件,不得不用上面向对象编程. 刚开始我的想法是: var datepi ...