C# 泛型,泛型約束
阿新 • • 發佈:2019-02-21
image info dialect pre LEDE read fan 問題 val
泛型主要是為了解決代碼的復用性
在泛型出現之前,如果需要用到不同的參數類型,但是方法體一樣的時候,需要定義多個不同類型參數的方法,這樣有太多的重復代碼如下
public static void ShowInt(int iParameter) { Console.WriteLine("類名稱:"+typeof(TestFunctionClass).FullName+",參數類型:"+ iParameter.GetType().ToString() + ",參數Value:"+iParameter); } publicstatic void ShowString(string sParameter) { Console.WriteLine("類名稱:" + typeof(TestFunctionClass).FullName + ",參數類型:" + sParameter.GetType().ToString() + ",參數Value:" + sParameter); } public static void ShowDate(DateTime dParameter) { Console.WriteLine("類名稱:" + typeof(TestFunctionClass).FullName + ",參數類型:" + dParameter.GetType().ToString() + ",參數Value:" + dParameter); }
在Main方法中進行調用
Console.WriteLine("最開始展示不同類型參數的信息的時候,需要定義多個不同類型的方法,而方法內容是幾乎一樣的"); TestFunctionClass.ShowInt(1); TestFunctionClass.ShowString("aaa"); TestFunctionClass.ShowDate(DateTime.Now); Console.ReadLine();
輸出結果
後來發現使用裏氏替換原則,任何使用父類的地方可以使用子類來進行替換,於是有了下面這種寫法(object是任何子類的父類)
public static void ShowObject(object oParameter) { Console.WriteLine("類名稱:" + typeof(TestFunctionClass).FullName + ",參數類型:" + oParameter.GetType().ToString() + ",參數Value:" + oParameter); }
在主方法中可以直接傳遞
Console.WriteLine("後來發現通過裏氏替換原則,任何父類出現的地方可以用子類來進行替換,可以節省大部分代碼"); TestFunctionClass.ShowObject(2); TestFunctionClass.ShowObject("bbb"); TestFunctionClass.ShowObject(DateTime.Now); Console.WriteLine("但是這樣出現一個問題,出現類類型之間的轉換,發生了裝箱操作,這樣使性能得到了非常大的損耗,(值類型轉換為引用類型)");
輸出結果
這個時候出現了泛型,泛型是在定義的時候,不直接聲明類型,直到調用的時候再去指定,延時聲明的作用,避免了裝箱操作,減少了性能損耗
public static void ShowFanXing<T>(T tParameter) { Console.WriteLine("類名稱:" + typeof(TestFunctionClass).FullName + ",參數類型:" + tParameter.GetType().ToString() + ",參數Value:" + tParameter); }
在主方法中調用
TestFunctionClass.ShowFanXing<int>(3); TestFunctionClass.ShowFanXing<string>("ccc"); TestFunctionClass.ShowFanXing<DateTime>(DateTime.Now); Console.WriteLine("使用泛型的時候性能和使用普通方法類似,遠大於通過object(裏氏替換原則)的性能(前提:如果發生了裝箱操作的時候");
輸出結果
這個時候,泛型的定義知道了,但是咱們發現好像泛型沒有什麽意義,在方法內只能使用的還是基類的一些屬性和方法
這個時候需要引入一個東西,泛型約束,通過泛型約束,咱們可以在泛型方法(泛型類)中使用約束的屬性和方法
先聲明一些基礎類
public class Pepple { public int Age { get; set; } public string Name { get; set; } public string SayHi() { return "Hi,My Name is" + Name + ",My Age Is " + Age; } } public class Chinese : Pepple, ISiChuan { public string Dialect { get; set; } public string Food() { return "火鍋"; } } public class Japanese : Pepple, IGuangDao { public string ViewSakura() { return "美しい桜"; } } public interface ISiChuan { string Dialect { get; set; } string Food(); } public interface IGuangDao { string ViewSakura(); }
泛型方法
public static void ShowPeople<T>(T tParameter) where T : Pepple { Console.WriteLine("名字:" + tParameter.Name + ",年齡:" + tParameter.Age); Console.WriteLine("說話:" + tParameter.SayHi()); }
在主方法中可以進行調用
Pepple people = new Pepple() { Age = 1, Name = "People Name" }; //裏氏替換原則 Pepple chinese = new Chinese() { Age = 1, Name = "張三" }; TestFunctionClass.ShowPeople<Pepple>(people); TestFunctionClass.ShowPeople<Pepple>(chinese); Console.WriteLine("這個時候還有一個問題,雖然用了泛型約束,可以使用約束類的屬性和方法,但是,子類的一些特性還是不能訪問,這個時候出現了接口約束"); Console.ReadLine();
輸出結果
泛型接口約束
public static void ShowPeopleDetail<T>(T tParameter) where T : Pepple, ISiChuan { Console.WriteLine("名字:" + tParameter.Name + ",年齡:" + tParameter.Age); Console.WriteLine("說話:" + tParameter.SayHi()); Console.WriteLine("喜歡吃:" + tParameter.Food()); }
執行結果
結束
C# 泛型,泛型約束