什么是泛型?
C# 語言和公共語言運行時 (CLR) 在 2.0 版本中添加了泛型。泛型將類型參數的概念引入 .NET Framework,這樣就可以設計具有相同特征的類和方法:在客戶端代碼聲明並初始化這些類和方法之前,這些類和方法會延遲指定一個或多個類型(使用占位符~3:數字代表類型參數個數)。
泛型有什么用?
使用泛型類型可以最大限度地重用代碼、保護類型安全性以及提高性能。泛型最常見的用途是創建集合類 List<int>。
可以創建:泛型接口、泛型類、泛型方法、泛型事件和泛型委托。
泛型約束有哪些?
where T : struct 類型參數必須是值類型。
where T : class 類型參數必須是引用類型。 此約束還應用於任何類、接口、委托或數組類型。
where T : unmanaged 類型參數不能是引用類型,並且任何嵌套級別均不能包含任何引用類型成員。
where T : new() 類型參數必須具有公共無參數構造函數。
where T : <基類名> 類型參數必須是指定的基類或派生自指定的基類。
where T : <接口名稱> 類型參數必須是指定的接口或實現指定的接口。
where T : U 為 T 提供的類型參數必須是為 U 提供的參數或派生自為 U 提供的參數。
某些約束是互斥的。 所有值類型必須具有可訪問的無參數構造函數。 struct
約束包含 new()
約束,且 new()
約束不能與 struct
約束結合使用。 unmanaged
約束包含 struct
約束。 unmanaged
約束不能與 struct
或 new()
約束結合使用。
泛型類:
class GenericClass<T> { }
泛型接口:
public interface GenericInterface<T>{}
泛型方法:(可以作為傳入參數,也可以作為返回值)
public T void Create<T>(T t) { return default(T) }
泛型委托:
public delegate void GenericDelegate<T>(T t);
實例使用泛型來種樹(模擬下螞蟻森林種樹):
最開始的時候森林里只有梭梭樹:
各個類代碼:
public class SuosuoTree { //種植梭梭樹需要的能量 public int needEnergy() { return 17900; } }
public class People { //姓名 public string name { get; set; } //能量 public int energy { get; set; } public void Plant(SuosuoTree tree) { if(energy< tree.needEnergy()) { Console.WriteLine("能量不足"); } { energy = energy- tree.needEnergy(); Console.WriteLine($"恭喜{name}, 梭梭樹種植成功,獲得成就!!"); } } }
public class People { //姓名 public string name { get; set; } //能量 public int energy { get; set; } public void Plant(SuosuoTree tree) { if(energy< tree.needEnergy) { Console.WriteLine("能量不足"); } { energy = energy- tree.needEnergy; Console.WriteLine($"恭喜{name}, 梭梭樹種植成功,獲得成就!!"); } } }
class Program { static void Main(string[] args) { People xiaoming = new People { name = "小明", energy = 200000 }; xiaoming.Plant(new SuosuoTree()); Console.WriteLine("剩余能量:"+xiaoming.energy); Console.Read(); } }
輸出結果為:
現在森林里可以種其他的樹了(檸條,樟子松)。那我們添加2個類,修改People類,和Main方法,那有什么辦法可以不修改People類的呢?
現在我們創建一個抽象類TreeBase:
public abstract class TreeBase { public abstract string GetTreeName(); public abstract int needEnergy(); } public class SuosuoTree: TreeBase { //種植梭梭樹需要的能量 public override int needEnergy() { return 17900; } public override string GetTreeName() { return "梭梭樹"; } } public class NingTiaoTree : TreeBase { //種植檸條需要的能量 public override int needEnergy() { return 16930; } public override string GetTreeName() { return "檸條"; } } public class ZhangZiSongTree : TreeBase { //種植樟子松需要的能量 public override int needEnergy() { return 146210; } public override string GetTreeName() { return "樟子松"; } }
重新構造后的People:修改后添加了新的樹苗,就不用修改People類了。
public class People { //姓名 public string name { get; set; } //能量 public int energy { get; set; } public void Plant<T>(T tree) where T:TreeBase { if(energy< tree.needEnergy()) { Console.WriteLine("能量不足"); } else { energy = energy- tree.needEnergy(); Console.WriteLine($"恭喜{name},{tree.GetTreeName()}種植成功,獲得成就!!"); } } }
小明也可以種不同的樹了:
class Program { static void Main(string[] args) { People xiaoming = new People { name = "小明", energy = 200000 }; xiaoming.Plant(new SuosuoTree()); xiaoming.Plant(new NingTiaoTree()); xiaoming.Plant(new ZhangZiSongTree()); Console.WriteLine("剩余能量:"+xiaoming.energy); xiaoming.Plant(new ZhangZiSongTree()); Console.Read(); } }