C#之泛型
阿新 • • 發佈:2019-01-10
參數 star 通過 cond 測試結果 form dcl work child
---恢復內容開始---
泛型即一個方法可以傳遞多種不同的類型的時候,就用泛型。泛型是C#2.0語法新特性,也是.net framework框架升級的結果。
//引入泛型 public class IntroduceGeneric { //普通方法 public void ShowInt(int i) { Console.WriteLine(i); } public void ShowString(string s) { Console.WriteLine(s); }public void ShowDateTime(DateTime t) { Console.WriteLine(t); } //泛型方法 public void Show<T>(T t) { Console.WriteLine(t); } }
static void Main(string[] args) { int i = 2; string s = "abc"; DateTime dateTime= DateTime.Now; IntroduceGeneric introduceGeneric = new IntroduceGeneric(); Console.WriteLine("普通方法"); introduceGeneric.ShowInt(i); introduceGeneric.ShowString(s); introduceGeneric.ShowDateTime(dateTime); Console.WriteLine("泛型方法"); introduceGeneric.Show<int>(i); introduceGeneric.Show<String>(s); introduceGeneric.Show<DateTime>(dateTime); }
從上面兩段代碼可以看出,用一個泛型方法可以代替多種普通的方法。這時候可以有人想到用object類型傳參,下面就試試obejct。
//泛型方法 public void Show<T>(T t) { Console.WriteLine(t); } //基於object類型傳參 public void ShowObject(object o) { Console.WriteLine(o); }
Console.WriteLine("泛型方法"); introduceGeneric.Show<int>(i); introduceGeneric.Show<String>(s); introduceGeneric.Show<DateTime>(dateTime); Console.WriteLine("用object類型傳參方法"); introduceGeneric.ShowObject(i); introduceGeneric.ShowObject(s); introduceGeneric.ShowObject(dateTime);
運行結果
從運行結果可以看出 ,泛型方法和object傳參沒有什麽區別。其實很容易理解,因為object 是一切類型的父類。下面我們從性能方面來比較泛型和object傳參方法。
public class PerformanceTest { public static IntroduceGeneric introduceGeneric = new IntroduceGeneric(); public static void CommonMethod() { Console.WriteLine("執行10000000次普通方法消耗時間"); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); int i = 10; for (var t = 0; t < 10000000; t++) { introduceGeneric.ShowInt(i); } stopwatch.Stop(); Console.WriteLine(stopwatch.ElapsedMilliseconds); } public static void GenericMethod() { Console.WriteLine("執行10000000次泛型方法消耗時間"); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); int i = 10; for (var t = 0; t < 10000000; t++) { introduceGeneric.Show<int>(i); } stopwatch.Stop(); Console.WriteLine(stopwatch.ElapsedMilliseconds); } public static void ObjectMethod() { Console.WriteLine("執行10000000次object參數方法消耗時間"); Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); int i = 10; for (var t = 0; t < 10000000; t++) { introduceGeneric.ShowObject(i); } stopwatch.Stop(); Console.WriteLine(stopwatch.ElapsedMilliseconds); } }
為了便於查看,將方法裏面的代碼置空,即不輸出上文中的內容。。下面就看比較結果
可以看出 泛型方法和普通方法幾乎一樣 甚至性能還由於普通方法 而object參數方法 則消耗的時間大概是泛型方法的兩倍。原因是object在上述過程中進行了大量的裝箱與拆箱操作。
泛型除了應用與泛型方法 還可以是泛型類、泛型接口 、泛型委托。
public class GenericClass<T> { public T t { get; set; } public void Fun() { this.t = default(T); Console.WriteLine(t?.ToString()); } } Console.WriteLine("泛型類"); GenericClass<int> genericClass = new GenericClass<int>(); genericClass.Fun(); GenericClass<string> genericClass2 = new GenericClass<string>(); genericClass2.Fun(); GenericClass<DateTime> genericTest3 = new GenericClass<DateTime>(); genericTest3.Fun();
測試結果:
泛型類的繼承
public class GenericChildClass : GenericClass<int> { } public class GenericChildClass2<T, S> : GenericClass<T> { } //註意當子類不是泛型類的時候,父類的泛型一定要指明具體的類型。如果不指明,父類的類型不能確定 //單子類中包含父類中的泛型類型時,父類可以不指明,以為這時唯一一個子類對應唯一一個父類
泛型接口,泛型委托
//泛型接口 public interface IGeneric<T> { void IFun(T t); } //泛型委托 public delegate void GenericDelegate<T>(T t);
泛型約束
public class People { public string Name { get; set; } public int Age { get; set; } } //泛型約束 public class GenericConstraint { //要求定義一個方法實現打印people的姓名和名稱 public void CommonPrint(People people) { Console.WriteLine($"姓名:{people.Name} 年齡:{people.Age}"); } public void GenericPrint<T>(T t) where T : People { Console.WriteLine($"姓名:{t.Name} 年齡:{t.Age}"); } public void ObjectPrint(object t) { //Console.WriteLine($"姓名:{t.Name} 年齡:{t.Age}");報錯 編譯不能通過 } } //泛型約束實現了可以訪問泛型約束了的公開方法和屬性、字段 //object參數方法則不行 這就是我們常說的類型安全問題
泛型約束的種類
1.基類約束
2.接口約束
3.值類型約束
4.引用類型約束
5.無參構造函數約束
//約束種類 public void GenericType<T>(T t) //where T : new()//基類約束 約束類型必須包含無參構造函數 其他有參構造函數可有可無 //where T:struct// 值類型約束 //where T:class//引用類型約束 //where T:ISport//接口約束 where T:People,ISport //多重約束,既是People類型(含子類) 並且實現了ISport接口(子類父類都可以) { }
---恢復內容結束---
C#之泛型