使用泛型的好处是“代码重用”,极大的提高了开发效率,泛型为开发者提供了以下优势:

    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#】泛型的更多相关文章

  1. clr via c# 泛型

    1,类型对象,对于应用程序的各种类型创建的对象叫做类型对象:Type object:对于泛型类型参数的类型,CLR同样也会创建内部类型对象,适用于 引用类型 值类型 接口类型 委托类型 具有泛型类型参 ...

  2. CLR VIA C# 泛型的协变和逆变

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  3. CLR via C#深解笔记六 - 泛型

    面向对象编程一个好处就是“代码重用”,极大提高了开发效率.如是,可以派生出一个类,让它继承基类的所有能力,派生类只需要重写虚方法,或添加一些新的方法,就可以定制派生类的行为,使之满足开发人员的需求. ...

  4. [CLR via C#]12. 泛型

    泛型(generic)是CLR和编程语言提供一种特殊机制,它支持另一种形式的代码重用,即"算法重用". 简单地说,开发人员先定义好一个算法,比如排序.搜索.交换等.但是定义算法的开 ...

  5. CLR类型设计之泛型(一)

    在讨论泛型之前,我们先讨论一下在没有泛型的世界里,如果我们想要创建一个独立于被包含类型的类和方法,我们需要定义objece类型,但是使用object就要面对装箱和拆箱的操作,装箱和拆箱会很损耗性能,我 ...

  6. CLR via C#关于泛型(Generics )的摘录

    泛型,是CLR和编程语言提供的一种特殊机制,它支持另一种形式的代码重用,即“算法重用”. 简单的说,开发人员先定义好一个算法,比如排序.搜索.交换.比较或者转换等.但是,定义算法的开发人员并不设改算法 ...

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

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

  8. 重温CLR(八 ) 泛型

    熟悉面向对象编程的开发人员都深谙面向对象的好处,其中一个好处是代码重用,它极大提高了开发效率.也就是说,可以派生出一个类,让他继承基类的所有能力.派生类只需要重写虚方法,或添加一些新方法,就可定制派生 ...

  9. 泛型(Generics)

    Framework类库中的泛型 泛型可以使代码重用,提高开发效率 CLR允许在引用类型.值类型或接口中定义泛型方法: CLR允许创建泛型引用类型.泛型值类型(枚举不允许创建).泛型委托类型和泛型接口类 ...

  10. CLR总览

    Contents 第1章CLR的执行模型... 4 1.1将源代码编译成托管代码模块... 4 1.2 将托管模块合并成程序集... 6 1.3加载公共语言运行时... 7 1.4执行程序集的代码.. ...

随机推荐

  1. php数据访问(查询)

    查询:常用关键字查询 和 准确查询 单条件查询 创建添加查询元素 <br /> <form action="main.php" method="post ...

  2. 用fontAwesome代替网页icon小图标

    1. 引言 网页小图标到处可见,如果一个网页都是干巴巴的文字和图片,而没有小图标,会显得非常简陋.下面的小图标,你是不是会经常用到? 你可能说——“我们用的都是彩色的,不是黑白的”——别着急,下面会讲 ...

  3. HTML认识

    1.1 认识什么是纯文本文件 txt window自带有一个软件,叫做记事本,记事本保存的格式TXT,就是英文text的缩写,术语上称呼为"纯文本文件" TXT文件,只能保存文本内 ...

  4. July 7th, Week 28th Thursday, 2016

    The 79th Anniversary of Anti-Japan War Difficulties vanish when faced bodly. 勇敢面对困难,困难自会退让. The best ...

  5. js中我的注释规范

    模块功能描述说明: /** * ------------------------------------------------------------------ * 模块描述说明 * ------ ...

  6. 解决java.lang.NoClassDefFoundError: org/apache/log4j/Level

    现象: java.lang.NoClassDefFoundError: org/apache/log4j/Level at org.slf4j.LoggerFactory.getSingleton(L ...

  7. ASP.NET SignalR 与 LayIM2.0 配合轻松实现Web聊天室(八) 之 用 Redis 实现用户在线离线状态消息处理

    前言 上篇的预告好像是“聊天室的小细节,你都注意到了吗?”.今天也是为那篇做铺垫吧.之前的版本有好多问题,比如:当前登录用户是否合法问题,userid参数如果随便传后台没有验证.还有一个致命的问题,用 ...

  8. Ionic2 Tutorial

    build your first app Now that you have Ionic and its dependencies installed, you can build your firs ...

  9. .NET Nancy 详解(二) 简易路由实现

    继续上面的简易版本,有意思的点剩下便是路由实现了. 路由注册 首先,来看一下基本的路由注册过程. public FakeNancyModuleWithoutBasePath() { Delete[&q ...

  10. html5 svg 圆形进度条

    html5 svg 圆形进度条 <!DOCTYPE html> <html lang="en"> <head> <meta charset ...