CLR via C#學習筆記-第十二章-泛型方法和其他成員
阿新 • • 發佈:2018-11-04
12.6 泛型方法
方法和類可以各自定義型別引數
定義泛型類、結構或介面時,型別中定義的任何方法都可以引用型別指定的型別引數。
型別引數可以作為方法引數、返回值或方法內部定義的區域性變數的型別使用。
CLR還允許方法指定他自己的型別引數,這些引數也可以作為引數、返回值或區域性變數的型別使用。
在下例中型別定義了一個型別引數,方法也定義了自己的:
internal sealed class GenericType<T>{ private T m_value; public GenericType(T value){m_value=value;}public TOutput Converter<TOutput>(){ TOutput result=(TOutput)Converter.ChangeType(m_value,typeof(TOutput); return result; } }
Converter方法將欄位引用的物件轉換成任意型別——具體取決於呼叫時傳遞的型別實參是什麼。
泛型方法的呼叫
泛型方法的一個很好的例子是Swap方法:
private static void Swap<T>(ref T o1,ref T o2){ T temp=o1; o1=o2; o2=temp; }
現在可以這樣呼叫Swap:
private static void CallingSwap(){ Int32 n1=1;n2=2; Swap<Int32>(ref n1,re n2); String s1="A",s2="B"; Swap<String>(ref s1,ref s2); }
為獲取out和ref引數的方法使用泛型型別很有意思,
因為作為out/ref實參傳遞的變數必需具有與方法引數相同的型別,以免損害型別安全性。
涉及out/ref引數的這個問題在9.3節已作討論。
泛型方法和型別推斷
C#編譯器支援在呼叫泛型方法是進行型別託短,增強可讀性、維護性:
private static void CallingSwap(){ Int32 n1=1;n2=2; Swap(ref n1,re n2); String s1="A"; Object s2="B"; Swap(ref s1,ref s2);//錯誤,不能推斷 }
即使s2是Object,即使他恰好引用一個String,由於s1,s2是不同的資料型別的變數,編譯器拿不準腰圍Swap傳遞什麼型別實參,所以會報錯。
方法過載為泛型
型別可以定義多個方法,讓其中一個方法接受具體資料型別,另一個接受泛型引數,如下所示:
private static void Display(String s){ Console.WriteLine(s); } private static void Display(T o){ Display(o.ToString()); }
下面展示了呼叫Display方法的一些方式:
Display("Jeff");//呼叫Display(String) Display(123);//呼叫Display<T>(T) Display<String>("Aidan");//呼叫Display<T>(T)
在第一個調研中,編譯器可以接受第一個String引數的方法也可以接受泛型Display方法。
但C#編譯器的策略是先考慮明確的匹配再考慮泛型匹配。否則會造成無限遞迴。
12.7 泛型和其他成員
在C#中,屬性、索引器、時間、操作符方法、構造器和終結器本身不能有型別引數,但它們能在泛型型別中定義。
之所以不允許他們指定自己的泛型型別引數,是因為微軟開發人員認為沒有必要,而且為這些成員新增泛型支援的代價是相當高的。