文章目錄
一、泛型概念
C# 語言和公共語言運行時 (CLR) 在 2.0 版本中添加了泛型。泛型將類型參數的概念引入 .NET Framework,這樣就可以設計具有相同特徵的類和方法:在客戶端代碼聲明並初始化這些類和方法之前,這些類和方法會延遲指定一個或多個類型(使用佔位符~3:數字代表類型參數個數)
二、泛型的作用
使用泛型類型可以最大限度地重用代碼、保護類型安全性以及提高性能。泛型最常見的用途是創建集合類 List< int>。
1.泛型分類:
泛型接口、泛型類
、泛型方法
、泛型事件和泛型委託
。
2.泛型的好處
(1)增加類型的安全性
(2)提高代碼的重用
三、泛型的使用
(一)泛型類
1.創建泛型類
2.案例:
//泛型類
class MyList<T>
{
T[] stack; //聲明數組
int size; //數組長度
int stacPoint; //當前位置指針(索引)
public MyList(int length)
{
this.size = length;
stack = new T[size];
stacPoint = -1;
}
// 入棧
public void Add(T item)
{
if (stacPoint>=size) //如果超過數組長度
{
Console.WriteLine("集合已滿");
}
else
{
stacPoint++;
stack[stacPoint] = item;
}
}
// 出棧
public T Pop()
{
T data = stack[stacPoint];
stacPoint--;
return data;
}
}
// 主運行窗口
static void Main(string[] args)
{
//實例化泛型類
MyList<int> list = new MyList<int>(6);
//入棧
list.Add(1);
list.Add(2);
list.Add(3);
list.Add(4);
list.Add(5);
//出棧
Console.WriteLine(list.Pop()); // 5
Console.WriteLine(list.Pop()); // 4
Console.WriteLine(list.Pop()); // 3
Console.WriteLine(list.Pop());// 2
Console.WriteLine(list.Pop());// 1
Console.ReadLine();
}
3.泛型類的規範:
public class 類名<T> {類成員....}
(1) T:僅代表一個佔位符
,用T或者其他字母都行,只要符合C#命名規範都行,但是一般情況用T
(2) T:表示一個通用的數據類型,在使用的時候用實際類型代替
(3)T:泛型類可以在定義中可以包含多個任意類型
參數,參數之間使用逗號隔開
如
public class 類名<T1,T2,T3,....>{...}
各種類型參數
都可以用作成員變量的類型
、屬性
、方法
等成員的返回類型,以及方法的參數類型
以上泛型類的使用,增加了類型安全,實例化時int類型的約束下是不能添加string類型。無需拆箱操作
4.泛型類型的問題
無法爲泛型類型賦值初始
因爲泛型類型可以理解爲泛指所有的數據類型,而所有的數據類型可分爲:值類型和引用類型,而且不同的數據類型支持的默認值是不一樣的。
注意:
(1) 不能隨便假設泛型類型是某種類型,這種類型也許沒有構造方法,也許是私有的
(2) 解決方案使用default關鍵字,如果defalut中指定的類型最終是引用類型則默認是null,如果是值類型那就給值類型對應的默認值,數值就是0.結構類型要根據具體的成員類型確定是0還是null
(二)泛型方法
案例
static void Main(string[] args)
{
Console.WriteLine(Add<int>(11,12));//23
Console.WriteLine(Add<double>(11.5,12.5));// 24
//Console.WriteLine(Add<char>('a','b'));//異常實參不爲值類型
Console.ReadLine();
}
//泛型方法
static T Add<T>(T a,T b) where T : struct
{
dynamic a1 = a; // 設置動態類型 根據程序執行動態獲取當前類型
dynamic b1 = b;
return a1 + b1;
}
四、泛型約束
1.泛型約束有哪些
- where T : struct 類型參數必須是值類型。
- where T : class 類型參數必須是引用類型。 此約束還應用於任何類、接口、委託或數組類型。
- where T : unmanaged 類型參數不能是引用類型,並且任何嵌套級別均不能包含任何引用類型成員。
- where T : new() 類型參數必須具有公共無參數構造函數。
- where T : <基類名> 類型參數必須是指定的基類或派生自指定的基類
- where T : <接口名稱> 類型參數必須是指定的接口或實現指定的接口
- where T : U 爲 T 提供的類型參數必須是爲 U 提供的參數或派生自爲 U 提供的參數。
2.案例
static void Main(string[] args)
{
MyGenericClass<int, Course, Teacher> myGener = new MyGenericClass<int, Course, Teacher>();
myGener.ProductList = new List<Course>()
{
new Course(){CourseName="ASP.NET",Period=6},
new Course{CourseName="WEB",Period=5}
};
Course c = myGener.GetClass(0);
Console.WriteLine($"{c.CourseName}課程的週期{c.Period}");
Console.ReadLine();
}
//泛型類
class MyGenericClass<T1, T2, T3>
where T1:struct //值類型
where T2:class //引用類型 (還包含:類,接口,委託,數組)
where T3:new () //無參數構造函數
{
public List<T2> ProductList { get; set; } //聲明以T2集合爲類型的屬性
public T3 Teachers { get; set; } //聲明以T3爲類型的屬性
//聲明以T2 爲返回類型、T1類型爲參數,的方法
public T2 GetClass(T1 num)
{
dynamic a = num; //根據T1獲取到a的數據類型
return ProductList[a]; //返回數組中a索引對應的數據
}
}
//參數類 T2:代表所學的科目類
class Course
{
/// <summary>
/// 課程名稱
/// </summary>
public string CourseName { get; set; }
/// <summary>
/// 學習週期
/// </summary>
public int Period { get; set; }
}
//參數類 T3:代表老師
class Teacher
{
/// <summary>
/// 姓名
/// </summary>
public string Name { get; set; }
/// <summary>
/// 授課數量
/// </summary>
public int Count { get; set; }
}