詳解C#泛型(二)

Minotauros發表於2018-11-15

  一、自定義泛型方法(Generic Method),將型別引數用作引數列表或返回值的型別:

void MyFunc<T>() //宣告具有一個型別引數的泛型方法
{
    Type genericType = typeof(T); //在泛型方法體內部獲取型別引數的型別資訊
    //do…
}
//呼叫泛型方法
MyFunc<int>();

  1.宣告泛型方法時,可以在引數列表中使用這個型別引數:void MyFunc<T>(T obj) { };此時在呼叫該泛型方法時可以省略型別引數的指定由編譯器推斷其型別,例如:MyFunc<int>(myNum)與MyFunc(myNum)完全等效;

  2.宣告泛型方法時,可以在返回值型別中使用這個型別引數:T MyFunc<T>() { return default(T); };編譯器的型別推斷功能不適用於僅在返回值型別中使用型別引數的情況,此種情況在呼叫時必須顯式指定型別引數;

  3.宣告泛型方法時,方法的引數列表和返回值可以指定相同或不相同的型別引數,如果不相同則一般引數列表的型別引數在前,返回值的型別引數在後:U MyFunc<T, U>(T obj) { return default(U); },此時依然不能使用編譯器的型別推斷功能;如果相同,則在呼叫時可以使用編譯器的型別推斷功能省略型別引數的顯式指定;
型別引數數量的不同,可以構成過載方法:

void MyFunc() { }
void MyFunc<T>() { }
void MyFunc<T, U>() { }

  4.泛型方法中的型別引數也可以指定約束;

  5.在泛型類中宣告的方法,方法的引數列表和返回值可以使用泛型類的型別引數作為型別;泛型方法可出現在泛型或具體型別中,只有當方法有屬於自己的型別引數時才是泛型方法,在泛型類中宣告泛型方法時,二者型別引數的佔位符不可以相同:

class MyClass<T> //宣告一個泛型類,型別引數佔位符為T
{
    void MyFunc(T obj) //宣告一個非泛型方法,使用泛型類的型別引數T作為引數型別
    {
        //do…
    }
    //不能宣告泛型方法void MyFunc<T>,泛型方法的型別引數佔位符不能與類的型別引數佔位符相同
    void MyFunc<U>(T obj1, U obj2) //宣告一個泛型方法,型別引數佔位符為U
    {
        //do…
    }
}
class MyClass //定義一個具體類
{
    void MyFunc<T>(T obj) //宣告一個泛型方法
    {
        //do…
    }
}            

   二、自定義泛型介面(Generic Interface),將型別引數用作引數列表或返回值的型別:

interface IMyInterface<T> //定義具有一個型別引數的泛型介面
{
    void MyFunc(T obj); //宣告引數為T的方法
}
//宣告泛型類繼承自泛型介面
public class MyClass<T> : IMyInterface<T>
{
    public void MyFunc(T obj)
    {
        //do…
    }
}
//指定型別引數為string型別,創角泛型類的例項賦值給泛型介面的變數
IMyInterface<string> iMyInterface = new MyClass<string>();

  1.適用於泛型類的規則基本也適用於泛型介面;

  三、自定義泛型委託(Generic Delegate),將型別引數用作引數列表或返回值的型別:

delegate void MyDelegate<T>(T obj); //定義具有一個型別引數的泛型委託,引數列表中有一個引數
void MyGenericFunc<T>(T obj) //宣告一個泛型方法,引數列表中有一個引數
{
    //do…
}
void MyFunc(string str)
{
    //do…
}
//宣告泛型委託的例項,指定型別引數為string型別,此時可匹配的方法簽名為void myFunc(string str)
MyDelegate<string> myDelegate;
//賦值一個指定型別引數為string的泛型方法
myDelegate = MyGenericFunc<string>;
//新增一個引數列表為string型別的具體方法
myDelegate += MyFunc;

  1.泛型委託同泛型類一樣,需要在例項化時指定型別引數的型別;

  2.泛型委託的例項同具體委託的例項一樣,只需要方法的引數列表和返回值型別相同即可進行匹配,因此不管目標方法是指定了符合要求型別的泛型方法還是具體方法都可以進行匹配; 

  四、反射中的泛型:

Type myType = typeof(MyClass<>); //獲取未指定任何型別引數的開放式構造類的型別資訊,多個型別引數時新增,:typeof(MyClass<,>)
myType = myType.MakeGenericType(typeof(int)); //通過型別資訊的例項方法MakeGenericType()構建指定所有型別引數的封閉式構造類的型別資訊,如未指定所有型別引數會丟擲異常ArgumentException
//也可以直接獲取封閉式構造類的型別資訊,當型別引數在一開始就確定時推薦使用此種方式
//myType = typeof(MyClass<int>); //多個型別引數時需要同時指定:typeof(MyClass<int, string>)

  1.通過反射只可以獲取未指定任何型別引數的開放式構造類的型別資訊和指定所有型別引數的封閉式構造類的型別資訊,即無法獲取MyClass<int, >的型別資訊;

 


如果您覺得閱讀本文對您有幫助,請點一下“推薦”按鈕,您的認可是我寫作的最大動力!

作者:Minotauros
出處:https://www.cnblogs.com/minotauros/

本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連線,否則保留追究法律責任的權利。

 

相關文章