一,什麼是泛型
1.這是一個Int類型的集合
public class IntList { int[] arr; int count; /// <summary> /// 獲取已儲存的元素的個數 /// </summary> public int Count { get { return count; } } public IntList(int length) { arr = new int[length]; } #region 1.0 向集合中 追加元素 +void Add(int ele) /// <summary> /// 向集合中 追加元素 /// </summary> /// <param name="ele"></param> public void Add(int ele) { //判斷當前已添加元素的個數 是否 大於 數組的容量 if (count >= arr.Length) { //建立 2倍 的新數組 int[] arrNew = new int[arr.Length * 2]; //將arr 裏的 數據 複製到 新數組中(重新數組的第0個位置開始存放) arr.CopyTo(arrNew, 0); //將新數組的引用 設置給 arr arr = arrNew; } //將元素 加入到 數組中 arr[count] = ele; //元素總個數 +1 count++; } #endregion #region 2.0 索引器 +int this[int index] public int this[int index] { get { if (index >= arr.Length) { throw new System.Exception("數組下標越界!"); } else { return arr[index]; } } set { if (index >= arr.Length) { throw new System.Exception("數組下標越界!"); } else { arr[index] = value; } } } #endregion
2.這是一個String類型集合
public class StringList { string[] arr; int count; /// <summary> /// 獲取已儲存的元素的個數 /// </summary> public int Count { get { return count; } } public StringList(int length) { arr = new string[length]; } #region 1.0 向集合中 追加元素 +void Add(int ele) /// <summary> /// 向集合中 追加元素 /// </summary> /// <param name="ele"></param> public void Add(string ele) { //判斷當前已添加元素的個數 是否 大於 數組的容量 if (count >= arr.Length) { //建立 2倍 的新數組 string[] arrNew = new string[arr.Length * 2]; //將arr 裏的 數據 複製到 新數組中(重新數組的第0個位置開始存放) arr.CopyTo(arrNew, 0); //將新數組的引用 設置給 arr arr = arrNew; } //將元素 加入到 數組中 arr[count] = ele; //元素總個數 +1 count++; } #endregion #region 2.0 索引器 +int this[int index] public string this[int index] { get { if (index >= arr.Length) { throw new System.Exception("數組下標越界!"); } else { return arr[index]; } } set { if (index >= arr.Length) { throw new System.Exception("數組下標越界!"); } else { arr[index] = value; } } } #endregion 當咱們操做這些集合的時候
IntList intList = new IntList(3); intList.Add(9); intList.Add(19); intList.Add(59); for (int i = 0; i < intList.Count; i++) { Console.WriteLine(intList[i]); } StringList stringList = new StringList(3); stringList.Add("9a"); stringList.Add("19b"); stringList.Add("59c"); for (int i = 0; i < stringList.Count; i++) { Console.WriteLine(stringList[i]); }
會發現變得只是類型,這樣重複的類型變換有什麼辦法解決了,這就須要用到泛型html
/// <summary> /// 自定義泛型集合類,帶泛型參數 /// </summary> /// <typeparam name="MyType">集合的元素類型</typeparam> public class MyGenericList<MyType>
{ MyType aValue; MyType[] arr; int count; //int a = MyType; #region 獲取已儲存的元素的個數 +int Count /// <summary> /// 獲取已儲存的元素的個數 /// </summary> public int Count { get { return count; } } #endregion public MyGenericList(int length) { arr = new MyType[length]; } #region 1.0 向集合中 追加元素 +void Add(MyType ele) /// <summary> /// 向集合中 追加元素 /// </summary> /// <param name="ele"></param> public void Add(MyType ele) { //判斷當前已添加元素的個數 是否 大於 數組的容量 if (count >= arr.Length) { //建立 2倍 的新數組 MyType[] arrNew = new MyType[arr.Length * 2]; //將arr 裏的 數據 複製到 新數組中(重新數組的第0個位置開始存放) arr.CopyTo(arrNew, 0); //將新數組的引用 設置給 arr arr = arrNew; } //將元素 加入到 數組中 arr[count] = ele; //元素總個數 +1 count++; } #endregion #region 2.0 索引器 +MyType this[int index] public MyType this[int index] { get { if (index >= arr.Length) { throw new System.Exception("數組下標越界!"); } else { return arr[index]; } } set { if (index >= arr.Length) { throw new System.Exception("數組下標越界!"); } else { arr[index] = value; } } } #endregion 如今調用則能夠變成
MyGenericList<int> intList = new MyGenericList<int>(3); intList.Add(9); intList.Add(19); intList.Add(59); for (int i = 0; i < intList.Count; i++) { Console.WriteLine(intList[i]); }
string 類型的則能夠
MyGenericList<string> stringList = new MyGenericList<string>(3); stringList.Add("9a"); stringList.Add("19b"); stringList.Add("59c"); for (int i = 0; i < stringList.Count; i++) { Console.WriteLine(stringList[i]); }
MyType只是至關於一個佔位符,用的時候用具體的類型來替換便可。他只能是一個類型,不能是具體的值。
泛型是指的帶類型參數的類,而不是類型參數自己。如public class MyList<T>{….}其中的MyList就是泛型,而T是類型參數。
泛型參數能夠有多個,好比MyList<T,MyType>也是能夠的
實例化一個引用類型的泛型,它在內存中分配的大小是同樣的。
實例化一個值類型的泛型,它在內存中分配的大小是不同的。
儘管如此,CLR仍是爲每一個不一樣的類型參數建立了不一樣的泛型類版本。
二.泛型的繼承數組
繼承一個泛型類時,必須爲其傳遞泛型參數!函數
public class Father<k,v>{}//父類this
定義子類時直接爲父類泛型參數賦值
public class Son:Father<int,string>
定義子類時把子類泛型參數賦給父類泛型參數 public class Son<w,y>:Father<int,string>
public class Son:Father<k,v> 這種是錯誤的,由於K,V不存在
三.泛型約束
public class MyGenericDog<T> where T:new()//約束 傳給 T 的類 必須包含一個 無參的構造函數 { T t; public MyGenericDog() { t = new T(); } }
在使用時必須保證類有一個無參的構造函數spa
private void btnNewT_Click(object sender, EventArgs e) { MyGenericDog<LittleDog> list = new MyGenericDog<LittleDog>(); }
public class LittleDog { public LittleDog() { } public LittleDog(string str) { } }
四.用來約束泛型參數 必須是某個類 或者某個類的子類code
class Dog { public void Shout(){} } class Cat { public void Walk(){} } class House<TPet,TPet2>where TPet:Dog where TPet2:Cat { public c(TPet p,TPet2 p2) { p1.Shout(); p2.Walk(); } }
1.一個泛型參數不容許多個基類約束,不能寫成htm
class House<TPet,TPet2>where TPet:Dog where TPet:Cat 由於不可能既是狗,又是貓。
2.不能爲密封類指定基類約束(string) 密封類即爲私有類。即sealed這種不能繼承的類。
3.也不能用nullable<T>
五.用來約束泛型參數必須是值類型或者引用類型
public struct A{} public class B{} public class C<T> where T:struct 值類型 { } public class C2<T> where T:class 引用類型 { } 好比上面的若是使用c<person>就會報錯
六.泛型方法
public void Test<k>() where k:new() { }
K能夠用在三個地方:blog
1.參數繼承
public void Test<k>(k a) { }
2.能夠在方法體內用到索引
public void Test<k>() where k:new() { k k1=new k(); }
3.能夠當返回值
public K Test<k>() where k:new() { return k; }
七.泛型方法的重載
void sayA()
{
}
void sayA<T>() { } void sayA<K>() { }
在使用時能夠看到智能提示出現兩個方法say,say<>說明他們不構成重載
void sayA<T>() { } void sayA<K>() { }
這樣是不行的,由於泛型方法只是個佔位符,編譯器會認爲是同一個方法
八.泛型方法重寫
子類當中約束where k:class是不能在子類中重寫。而where k:new()不須要些,從父類中繼承過來了。