c#2.0比c#1.0有一點最大的改進就是加入對泛型的支持。泛型起源於c++語言的模板機制。這樣在c#中就避免了不必要的拆裝箱操作,而且還加強了編譯時的安全性,強類型的檢查。
CLR#允許創建泛型引用類型,值類型,但是不許創建泛型枚舉類型。 還可以創建泛型接口,委託,以及最常見的泛型方法。
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>
下面展示如何使用其中的一些泛型方法:
Byte[] byteArray = new Byte[] {5, 1, 4, 2, 3};
Array.Sort<Byte>(byteArray);
Int32 i = Array.BinarySearch<Byte>(byteArray, 1);
Console.WriteLine(i); // Displays "0"
}
下面看一下泛型的同一性:
}
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
記住顯示的方法優於泛型方法被調用:
{
Console.Write("Generic");
}
void Swap(double arg1,double,arg2)
{
Console.Write("Common");
}
//下面將會調用第二個方法
Swap(12.36,36.21);
下面看一下泛型約束,這一點是c#泛型的優勢:
約束分爲三種:主要約束,次要約束,和構造器約束
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();
}
}
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沒有關係
}
internal sealed class ConstructorConstraint<T> where T : new() {
public static T Factory() {
return new T(); //指定了構造器約束,我們可以肯定能夠返回一個T類型的實例
}
}
下面我們在看一些其他的問題:
T temp = default(T); // OK
}
//如果我們在不指定約束的時候想初始化T類型,那麼我們必須使用default關鍵字,這樣當T是引用類型時,temp被初始化爲null,如果T爲值類型temp被初始化爲0
還有就是一些基元操作符(/,*,+,-,等等)不能應用在泛型參數上:
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'