C#泛型約束
本文將對各類泛型約束做一個簡單的總結。
文章一開始,給出演示代碼底稿(在此基礎上修改,演示,說明。)
class MyList<T>
{
List<T> list = new List<T>();
public T this[int i]
{
get { return list[i]; }
set { this.list[i] = value; }
}
}
class Person
{
public string Name { get; set; }
}
接下來,依次修改演示代碼底稿,來說明不同類型的泛型約束。
1 指定泛型參數為值類型
class MyList<T> where T:struct
{
...代碼省略部分
}
看看加上約束後的效果怎麽樣,按下面方式 實例化MyList 類 :
MyList<Person> list = new MyList<Person>();
你會發現,將產生如下錯誤提示:
類型“GencConstraint.Person”必須是不可為 null 的值類型才能用作泛型類型或方法“GencConstraint.MyList<T>”中的參數“T”。
使用下面的方式實例化MyList 類 ,將一切正常:
MyList<int> list = new MyList<int>();
2 指定泛型參數為引用類型
class MyList<T> where T:class
{
...代碼省略部分
}
修改泛型約束為 引用類型後,前面的錯誤提示消失,因為 Person 類是引用類型,滿足泛型約束。
3 指定泛型參數有無參的公共的構造函數
class MyList<T> where T:new()
{
...代碼省略部分
}
為Person類增加私有的無參構造函數,代碼如下:
class Person
{
public string Name { get; set; }
private Person()
{
//do nothing
}
}
實例化 MyList < Person > 類:
MyList<Person> list = new MyList<Person>();
出現編譯錯誤,提示:
“GencConstraint.Person”必須是具有公共的無參數構造函數的非抽象類型,才能用作泛型類型或方法“GencConstraint.MyList<T>”中的參數“T”。
哈哈,約束起作用了。
4 指定泛型參數 必須派生於指定基類
增加抽象類 SeniorAnimal
abstract class SeniorAnimal//高級動物
{
public abstract void Speak();//會說話
public abstract void UseTool();//會使用工具
}
指定泛型參數 必須派生於基類 SeniorAnimal
class MyList<T> where T : SeniorAnimal
{
...代碼省略部分
}
實例化 MyList < Person > 類(此時Person類還未繼承自 SeniorAnimal 類 ):
MyList<Person> list = new MyList<Person>();
出現編譯錯誤,提示:
不能將類型“GencConstraint.Person”用作泛型類型或方法“GencConstraint.MyList<T>”中的類型參數“T”。沒有從“‘GencConstraint.Person”到“GencConstraint.SeniorAnimal”的隱式引用轉換。
修改代碼,使Person類繼承自 SeniorAnimal 類
class Person : SeniorAnimal
{
public string Name { get; set; }
public override void Speak()
{
Console.WriteLine("我會說臟話!");
}
public override void UseTool()
{
Console.WriteLine("我會用砍刀!");
}
}
再次編譯,一切正常。
5 指定泛型參數 必須實現指定接口
演示情況和第4點類似,就不提供演示代碼了。
6 指定泛型參數 必須派生於泛型類型U(裸類型約束)
class MyList<U> where U : SeniorAnimal
{
List<U> list = new List<U>();
public void ShowInfo<T>() where T : U
{
}
}
另外,可以為同一泛型參數應用多個約束。
好了,Game Over!
C#泛型約束