泛型

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'
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章