【Clr in c#】泛型

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

    1,源代码保护  算法的源代码不需要提供给使用泛型算法的开发人员,使用c++模板的泛型技术需要提供。(目前c++模板的泛型技术了解较少)

    2,类型安全    给泛型算法指定类型时,编译器能理解开发者意图,只有兼容类型能通过,不兼容的时候编译时候会报错。

    3,更清晰的代码  由于编译器强制类型的安全性,减少源代码中必须进行的转型次数,使得代码容易维护和编写。例如:DateTime dt=dtList[0];从DateTime的集合中按照索引取出来的值可以直接赋值给DateTime类型,不需要转型。

    4,更佳的性能 在操作值类型时候,非泛型集合会造成装箱、拆箱操作,会造成托管堆上的内存分配,会造成频繁的垃圾回收,影响性能。

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);
        }

  

时间: 2024-11-03 10:31:37

【Clr in c#】泛型的相关文章

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

面向对象编程一个好处就是“代码重用”,极大提高了开发效率.如是,可以派生出一个类,让它继承基类的所有能力,派生类只需要重写虚方法,或添加一些新的方法,就可以定制派生类的行为,使之满足开发人员的需求. 泛型(generic)是CLR和编程语言提供的一种特殊机制,它支持另一种形式的代码重用,即“算法重用”. 简单地说,开发人员先定义好一个算法,比如排序.搜索.交换.比较或转换等.但是,定义算法的开发人员并不设定该算法要操作什么数据类型:该算法可以广泛地应用于不同类型的对象.然后,另一个开发人员只要指

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

第十二章 泛型 2014-06-15 初始泛型12.3 泛型基础结构  12.3.1 开放类型与封闭类型  12.3.2 泛型类型和继承  12.3.3 泛型类型同一性  12.3.4 代码爆炸参考 初始泛型[1][2] 返回 泛型(generic)是CLR和编程语言提供一种特殊机制,它支持另一种形式的代码重用,即"算法重用". 简单地说,开发人员先定义好一个算法,比如排序.搜索.交换等.但是定义算法的开发人员并不设定该算法要操作什么数据类型:该算法可广泛地应用于不同类型的对象.然后,

CLR类型设计之泛型(一)

在讨论泛型之前,我们先讨论一下在没有泛型的世界里,如果我们想要创建一个独立于被包含类型的类和方法,我们需要定义objece类型,但是使用object就要面对装箱和拆箱的操作,装箱和拆箱会很损耗性能,我们接下来会用一个示例来说明使用泛型和使用非泛型对值操作时的性能差距.但是如果使用泛型,也是同样的效果,不需要装箱和拆箱的同时泛型还保证了类型安全 言归正传,.Net自2.0以后就开始支持泛型,CLR允许创建泛型引用类型和泛型值类型,但不允许创建泛型枚举类型,此外,CLR还允许创建泛型接口和泛型委托.

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

泛型,是CLR和编程语言提供的一种特殊机制,它支持另一种形式的代码重用,即“算法重用”. 简单的说,开发人员先定义好一个算法,比如排序.搜索.交换.比较或者转换等.但是,定义算法的开发人员并不设改算法要操作什么数据类型:改算法可广发地应用于不同类型的对象.然后,另一个开发人员只要指定了算法要操作的具体数据类型,就可以开始使用这个现成的算法了.例如,可用一个排序算法来操作Int32 和String等类型的对象. 1.大多数算法都封装在一个类型中,CLR允许创建泛型引用类型和泛型值类型,但不允许创建

第12章 泛型

泛型(generic)是CLR和编程语言提供的一种特殊机制,它支持另一种形式的代码重用,即算法重用. 简单的说,开发人员先定义好一个算法,比如排序.搜索.交换.比较或者转换等.但是,定义算法的开发人员并不设定该算法要操作什么数据类型.该算法可以广泛地应用于不同类型的对象.然后,另一个开发人员,只有指定了算法要操作的具体数据类型,就可以开始使用这个现成的算法了.例如,可以用一个排序算法来操作Int32和String等类型对象. 大多数算法都封装在一个类型中,CLR允许创建泛型引用类型和泛型值类型,

深入.net平台和c#编程 学习笔记

深入.net平台和c#编程 一:理解.nteFramwork与c# 1.1,:Microsoft.net框架概述 1.2:.net框架结构 1.3.:c#语言概述 1.4:体验框架类库的强大功能 二:用对象思考:属性和方法 2.1:类和对象 2.2::编写一个自己的类 2..3:综合实践 三:用对象思考:值类型和应用类型 3.1:在类中使用几种新的数据类型 3.2::理解c#中的值类型和引用类型 3.3:在类中使用索引器 3.4:使用类图描述类和类成员 四:用集合组织相关数据 4.1::集合概述

Java,泛型类型通配符和C#对照

c#的泛型没有类型通配符,原因是.net的泛型是CLR支持的泛型,而Java的JVM并不支持泛型,仅仅是语法糖,在编译器编译的时候都转换成object类型 类型通配符在java中表示的是泛型类型的父类 public void test(List<Object> c) { for(int i = 0;i < c.size();i++) { System.out.println(c.get(i)); } } //创建一个List<String>对象 List<String&

C#泛型方法解析

C#2.0引入了泛型这个特性,由于泛型的引入,在一定程度上极大的增强了C#的生命力,可以完成C#1.0时需要编写复杂代码才可以完成的一些功能.但是作为开发者,对于泛型可谓是又爱又恨,爱的是其强大的功能,以及该特性带来的效率的提升,恨的是泛型在复杂的时候,会呈现相当复杂的语法结构.这种复杂不仅是对于初学者,对于一些有开发经验的.NET开发者,也是一个不那么容易掌握的特性. 接下来我们来了解一下C#2.0加入的特性:泛型. 一.泛型的基本特性概述: 在实际项目开发中,任何API只要将object作为

《CLR.via.C#第三版》第二部分第12章节 泛型 读书笔记(六)

终于讲到泛型了.当初看到这个书名,最想看的就是作者对泛型,委托,反射这些概念的理解.很多人对泛型的理解停留在泛型集合上,刚开始我也是,随着项目越做越多,对待泛型的认识也越来越深刻. 泛型的概念:泛型是一种特殊的类型,它把指定类型的工作推迟到客户端代码声明并实例化类或方法的时候进行. 泛型的优势:源代码保护.类型安全.更加清晰的代码.更佳的性能. 原理:(关键字:开放类型,封闭类型)所有带泛型参数的类型都是一个开放式类型,它不能被实例化(类似接口),在具体使用时生成封闭类型(实际数据类型). 泛型