1. 程式人生 > 其它 >C# 語法之泛型

C# 語法之泛型

一.什麼是泛型

  泛型其實就是一個不確定的型別,可以在類或方法上使用。泛型在宣告期間沒有明確定義型別,編譯後生成一個佔位符,只有在呼叫後傳入型別,才會將該確切的型別將佔位符替換掉。

二.泛型的定義

//用在類中
public class ClassName<CName>
{
    //用在方法中
    public void Mothed<MName>() {
        
    }

    //泛型類中具體使用CName
    //返回值為CName並且接受一個型別為CName型別的物件
    public CName GetC(CName c) {

    }
}

  這裡的CName和MName是可變的型別(名字也是可變),可以讓呼叫者來決定要使用的型別。

三.使用

  下面舉個例子。

public class Animal
{
    //會跑的方法
    public virtual void CanRun()
    {
        Console.WriteLine("Animal Run Can");
    }
}

public class Dog : Animal
{
    //重寫父類方法
    public override void CanRun()
    {
        Console.WriteLine("Dog Can Run
"); } } public class Cat : Animal { //重寫父類方法 public override void CanRun() { Console.WriteLine("Cat Can Run"); } }

  再定義一個animalHouse來存放所有的動物。

public class AnimalHouse
{
    private List<Animal> animals = new List<Animal>();

    //新增方法
    public void AddAnimal(Animal a)
    {
        animals.Add(a);
    }
}

  AnimalHouse可以存放所有的動物,但如果取出來,使用就有些不方便。現在放進去Dog和Cat,你可以將所有動物都帶出來跑步。假如Dog有個方法是Canswin()游泳的方法,那這裡是調用不了,animal沒有這個方法。

  如果使用泛型的話,就可以由呼叫者決定使用哪種型別。在AnimalHouse將所有animal改為泛型。

public class AnimalHouse<T>
{
    private List<T> animals = new List<T>();

    //新增方法
    public void AddAnimal(T a)
    {
        animals.Add(a);
    }
}

  AnimalHouse想存放什麼型別,由呼叫者決定。

//宣告存放所有Dog型別的集合
AnimalHouse<Dog> dog = new AnimalHouse<Dog>();
//宣告存放所有Cat型別的集合
AnimalHouse<Cat> cat = new AnimalHouse<Cat>();

  傳入哪個型別,原本的T就會編譯成具體的型別。animalHouse可以讓我們來自己構造存放哪種動物的集合。該集合就可以具體使用集合中動物特有的方法。

  這裡還有個問題,原本AnimalHouse只能存放animal,現在是泛型T,那就算是非animal的類也可以存進去,不符合最初的設計。所以為了型別安全,需要對傳入的型別進行約束。

四.泛型約束

  泛型約束就是對泛型(傳入的型別)進行約束,約束就是指定該型別必須滿足某些特定的特徵,例如可以被例項化,實現Animal類等。舉個例子。

class Base { }
class Test<T, U>
    where U : struct
    where T : Base, new()
{ }

  使用的話,只需要在泛型後面加上where來使用。

  where T : struct。型別必須為值型別。

  where T : class。型別必須為引用型別。

  where T : new()。型別引數必須具有公共無引數建構函式。與其他約束一起使用時,new()約束必須最後指定。

  where T : <基類名>。型別引數必須是指定的基類或派生自指定的基類。

  where T : <介面名稱>。型別引數必須是指定的介面或實現指定的介面。可指定多個介面約束。約束介面也可以是泛型。

  然後,我們來為AnimalHouse新增泛型約束為:必須包含公共無參建構函式和基數必須為Animal。

//Animal約束T必須是Animal的子類或者本身,new()約束放在最後
public class AnimalHouse<T> where T : Animal, new()
{
    private List<T> animals = new List<T>();

    //新增方法
    public void AddAnimal(T a)
    {
        //呼叫CanRun方法
        //如果不加Animal泛型約束是無法呼叫.CanRun方法的,因為型別是不確定的
        a.CanRun();

        animals.Add(a);
    }
}

  現在AnimalHouse類限制要傳入的引數是,必須繼承Animal,且有公共無參建構函式的。