泛型

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