泛型

32 篇文章 0 订阅

c#2.0比c#1.0有一点最大的改进就是加入对泛型的支持。泛型起源于c++语言的模板机制。这样在c#中就避免了不必要的拆装箱操作,而且还加强了编译时的安全性,强类型的检查。

CLR#允许创建泛型引用类型,值类型,但是不许创建泛型枚举类型。 还可以创建泛型接口,委托,以及最常见的泛型方法。

// c#中的泛型集合类:
List < T >
Dictionary
< TKey, TValue >
SortedDictionary
< TKey, TValue >
Stack
< T >
Queue
< T >
LinkedList
< T >

// c#中的泛型接口:
IList < T >
IDictionary
< TKey, TValue >
IConection
< T >
IEnumerator
< T >
IEnumerable
< T >
IComparer
< T >
IComparable
< T >

下面展示如何使用其中的一些泛型方法:

public   static   void  Main()  {
Byte[] byteArray 
= new Byte[] {51423};
Array.Sort
<Byte>(byteArray);
Int32 i 
= Array.BinarySearch<Byte>(byteArray, 1);
Console.WriteLine(i);                                                              
// Displays "0"
}

下面看一下泛型的同一性:

internal   sealed   class  DateTimeList : List < DateTime >   {
}

DateTimeList dt 
=   new  DateTimeList();                                             // 这样写省去了<>括号,看起来简便了

 
/*这样会返回false,也就是如果一个方法参数允许接受DateTimeList类型,那么我们不可以把List<DateTime>传给他,因为这两个类型不相等,但是如果一个方法参数允许接受List<DateTime>类型,那么可以把一个DateTimeList传过去,因为他们之间存在继承关系*/
Boolean sameType 
=  ( typeof (List < DateTime > ==   typeof (DateTimeList));                     

// 如果我们想简便写法,可以像下面这样写:
using  DateTimeList  =  System.Collections.Generic.List < System.DateTime > ;
Boolean sameType 
=  ( typeof (List < DateTime > ==   typeof (DateTimeList));                              // 返回true


记住显示的方法优于泛型方法被调用:

void  Swap < T > (T arg1,Targ2)
{
           Console.Write(
"Generic");
}


void  Swap( double  arg1, double ,arg2)
{
              Console.Write(
"Common");
}


// 下面将会调用第二个方法
Swap( 12.36 , 36.21 );

下面看一下泛型约束,这一点是c#泛型的优势:

约束分为三种:主要约束,次要约束,和构造器约束

/*主要约束:类型参数可以指定0或者1个主要的泛型约束,主要约束可以是值类型也可以是引用类型,指定引用类型时,那么就意味着参数必须是这个引用类型或者从这个引用类型派生,还有两个特殊的主要约束:即class和struct约束,下面看一下代码:*/

internal   sealed   class  PrimaryConstraintOfStream < T >   where  T : Stream  {
public void M(T stream) {
stream.Close();
// OK
}

}


PrimaryConstraintOfStream
< Stream >  pcs = new  PrimaryConstraintOfStream < Stream > ();                           //  合法
PrimaryConstraintOfStream < FileStream >  pcs = new  PrimaryConstraintOfStream < FileStream > ();              // 合法
PrimaryConstraintOfStream < int >  pcs = new  PrimaryConstraintOfStream < int > ();                                        // 非法

// class约束
internal   sealed   class  PrimaryConstraintOfClass < T >   where  T :  class   {
public void M() {
T temp 
= null;                   //合法,因为已经约束了T为引用类型
}

}


// struct约束
internal   sealed   class  PrimaryConstraintOfStruct < T >   where  T :  struct   {
public static T Factory() {
return new T();
}

}
/*次要约束:一个类型参数可以指定0个或者多个次要约束。次要类型代表的是一个接口约束。还有一种辅助约束是类型参数之间必须存在某种关系。下面看个例子:*/

private   static  List < TBase >  ConvertIList < T, TBase > (IList < T >  list)
where  T : TBase  {
List
<TBase> baseList = new List<TBase>(list.Count);
for (Int32 index = 0; index < list.Count; index++{
baseList.Add(list[index]);
}

return baseList;
}


private   static   void  CallingConvertIList()  {
IList
<String> ls = new List<String>();
ls.Add(
"A String");

IList
<Object> To = ConvertIList<String, Object>(ls);

IList
<IComparable> lc = ConvertIList<String, IComparable>(ls);

IList
<IComparable<String>> lcs =ConvertIList<String, IComparable<String>>(ls);

IList
<String> ls2 = ConvertIList<String, String>(ls);

IList
<Exception> le = ConvertIList<String, Exception>(ls);                                                    // Error,string类型和Exception没有关系
}
// 构造器约束:一个指定的类型实参实现了一个public无参构造器的一个非抽象类型。如果同时指定了构造器约束和struct约束,编译器会报错,因为值类型都隐式的提供了一个无参构造器*/

internal   sealed   class  ConstructorConstraint < T >   where  T :  new ()  {
public static T Factory() {
return new T();                               //指定了构造器约束,我们可以肯定能够返回一个T类型的实例
}

}

下面我们在看一些其他的问题:

private   static   void  SettingAGenericTypeVariableToDefaultValue < T > ()  {
T temp 
= default(T); // OK
}


// 如果我们在不指定约束的时候想初始化T类型,那么我们必须使用default关键字,这样当T是引用类型时,temp被初始化为null,如果T为值类型temp被初始化为0

还有就是一些基元操作符(/,*,+,-,等等)不能应用在泛型参数上:

private   static  T Sum < T > (T num)  where  T :  struct   {
T sum 
= default(T) ;
for (T n = default(T); n < num; n++)
sum 
+= n;
return sum;
}


// 编译器报错
• error CS0019: Operator  ' < '  cannot be applied to operands of type  ' T '  and  ' T '
• error CS0023: Operator 
' ++ '  cannot be applied to operand of type  ' T '
• error CS0019: Operator 
' += '  cannot be applied to operands of type  ' T '  and  ' T '
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值