c# 泛型的理解(转)

所谓泛型,即通过参数化类型来实现在同一份代码上操作多种数据类型,泛型编程是一种编程范式,它利用“参数化类型”将类型抽象化,从而实现更灵活的复用。

C#泛型赋予了代码更强的类型安全,更好的服用,更高的效率,更清晰的约束。

机制:

C#泛型能力是由CLR在运行时支持的,区别于C++的编译时模板机制,和Java的编译时的“搽拭法”。这使得泛型能力可以在各种支持CLR语言之间进行无缝的互操作。

C#泛型代码在被编译为IL代码和无数据时,采用特殊的占位符来表示泛型机制,并用转悠的IL指令支持泛型操作,而真正的泛型实例化以“on-demand”的方式,发生在JIT编译时

C#泛型编译机制:

第一轮编译时,编译器只为Stack<T>(栈算法)类型产生“泛型版”的IL代码与元数据并不进行泛型的实例化,T在中间只充当占位符。

JIT编译时,当JIT编译器第一次遇到Stack<int>时,将int替换“泛型版”IL代码与元数据中的T—进行泛型类型的实例化。

CLR为所有类型参数为“引用类型”的泛型类型产生同一份代码;但是如果类型参数为“值类型”,对没一个不同的“值类型”,CLR将为其产生一份独立的代码。

C#泛型的特点

如果实例化泛型类型的参数相同,那么JIT编译器会重复使用该类型,因此c#的动态泛型能力避免了c++静态模板可能导致的代码膨胀的问题;

C#泛型类型携带有丰富的元数据,因此C# 的泛型类型可以应用于强大的反射机制

C# 的泛型类型采用“基类、接口、构造器、值类型、引用类型”的约束方式来实现对类型能数的“显式约束“,提高了类型安全的同时,也丧失了c++模板基于“签名”的隐式所具有的高灵活性

泛型类型的成员

泛型类型的成员可以使用泛型类型声明中的类型参数,但是类型参数如果没有任何约束,则只能在该类型上使用从System.Object继承的共有成员

泛型接口

泛型接口的类型参数要么实例化,要么来源于实现类声明的类型参数

泛型委托

Delegate bool Predicate<T>(T value)

Class x{

  Static bool F(int i){}

  Static bool G(string s){}

  Static void Main()

  {

   Predicate<string> p2=G;

   Predicate<inr> p1=new Predicate<Int> (F);

}

}

泛型委托支持在委托返回值和参数上应用参数类型,这些参数类型同样可以附带合法的约束

泛型方法简介

C#泛型机制只支持“在方法声明上包含类型参数”泛型方法

泛型机制不支持在除方法外的其他成员(属性、事件、所引起、构造器、析构器)的声明上包含类型参数,但是这些成员本身可以包含在泛型类型中,并使用泛型类型的类型参数

泛型方法既可以包含在泛型类型中,也可以包含在非泛型类型中

Public class Finder{

 Public static int Find<T>(T[]items,T item){

  For(int i=0;i<items.Legth;i++)

  {

   If(--)return I;

}

Return -1;

}

}

泛型方法调用

Int i=Finder.Find<int>(new int[]{1,2,3,4,5,},6);

泛型方法的重载

Class MyClass

{

 Void F1<T>(T[] a,int i);//不可以构成重载方法

 Void F1<U>(U[] a,int i)

 

 Void F2<T>(int x);可以构成重载方法

 Void F2int x);

 

 Void F3<T>(T t)where T:A

 Void F3<T>(T t)where T:B

}

泛型方法的重写

Abstract class base

{

 Public abstract T F<T,U>(T t,U u) where U:T;

 Public abstract T G<T>where U:ICompareable

}

Class Derived:Base

{

  //合法的重写,约束被默认继承

  Public override X F<X x,Y y>{}

 //非法的重写,指定的任何约束都是多余的

 Public override T G<T t> where T:Compareable(){}

}

 

泛型约束简介

C#泛型要求对“所有泛型类型或泛型方法的类型参数”的任何假定,都要基于“显示的约束”,以维护C# 所要求的类型安全

“显示约束”由where子句表达,可以指定“基类约束”、“接口约束”、“构造器约束”、“值类型/引用类型约束”供4中约束

“显示约束”并非必须,如果没有指定“显示约束”,泛型类型参数将只能方法System.Object类型中的共有方法

以下是4中约束:

构造器约束

Class A{public A(){}}

Calss B{public B(int i){}}

Class C<T> where T:new()

{

//可以在其中使用T t=new T();

}

C<A> c=new C<A>();//可以;A有无参构造器,必须有一个却省的默认值

C<B> c=new C<B>();//错误,B没有无参构造器

值类型/引用类型约束

Public struct A{}

Public class B{}

Clss C<T> where T:struct

{

//T在这里是一个值类型

}

 

C<A> c=new C<A>();//可以;A是一个值类型

C<B> c=new C<B>();错误,B是一个引用类型

基于约束

基类约束

Class A {public void F1(){}}

Class B{public void F2(){}}

Class C<S,T>

  Where S:A//S继承自A

  Where T:B//T继承自B

{

//可以在类型为S的变量上条用F1

//可以在类型为T的变量上调用F2

}

接口约束

Interface IPrintable{ void Pint();}

Interface ICompareable<T>{int CompareTo(T v);}

Interface IKeyProvider<T>{T GetKey();}

Class Dicationary<K,V>

  Where K:ICompareable<K>

  Where V:IPrintable,IKeyProvider<K>

{

  //可以在类型为K的变量上调用CompareTO

  //可以在类型为V的变量上调用PintGetKey

}

 

  泛型的设计是用来减少你重复实现代码的次数-只需要改变数据类型即可。因为抽象数据结构,如队列、栈和列表皆是典型的数据结构,所以存在针对这些东西的泛型类型完全可以理解,你可以从.Net中派生大量的值-通过使用现有的泛型类型。

泛型的意义

  泛型的意义何在?类型安全和减少装箱、拆箱并不是泛型的意义,而是泛型带来的两个好处而已(或许在.net泛型中,这就是明显的好处)泛型的意义在于—把类型作为参数,它实现了代码见的很好的横向联系,我们知道继承为了代码提供了一种从上往下的纵向联系,单泛型提供了方便的横向联系(从某种程度上说,它和AOP在思想上有相同之处)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值