1. 程式人生 > 其它 >C# 泛型的型別約束

C# 泛型的型別約束

  對於沒有型別約束的泛型,其型別引數可以指定為任意型別。

  例如List<T>,其型別引數T是值型別(List<int>)或引用型別(List<objiect>)。

  有時候,我們希望泛型的型別引數只能是值型別或引用型別,這時就該論到型別約束上場了。

  約束要放到泛型方法或泛型型別宣告的末尾,並由關鍵字where來引入。

  在C#中,有4中型別約束可供使用。

1、引用型別約束

  這種約束用於確保使用的型別實參是應用型別。型別實參可以是任何類。介面。陣列。委託,或者已知是引用型別的另外一個型別引數。例如以下宣告:

    class Sample<T> where
T : class

Sample<object>、Sample<int[]>等引用型別作為型別實參的是有效的。

Sample<int>、Sample<Color>等值型別作為型別實參的無效的。

2、值型別約束

  這種約束用於確保使用的型別實參是值型別的,包括列舉、結構體等,但可空型別除外。例如以下宣告:

    class Sample<T> where T : struct

Sample<int>、Sample<Color>等值型別作為型別實參的有效的。

Sample<object>、Sample<int[]>等引用型別作為型別實參的是無效的。

3、建構函式型別約束

  建構函式型別約束表示為T:new(),如果有多個型別引數,必須是所有型別引數的最後一個引數。它檢測型別實參是否有一個可用於型別例項的無參構造體。這適用於所有值型別;所有沒有顯式宣告構造體的非靜態類、非抽象類;所有顯式聲明瞭一個無參建構函式的非抽象類。例項如下:

    public T Create<T>() where T : new()
    {
        return new T();
    }

Create<int>()、Create<object>()都是有效的,但是Create<string>是無效的,因為string沒有無參建構函式。

4、轉換型別約束

  最後一種型別約束允許你指定另一種型別,型別實參必須可以通過一致性、引用或裝箱轉換隱式地轉換為該型別。一些例子如下:

        class Sample<T> where T : Stream { }//有效:Sample<Stream>(一致性轉換)
                                            //無效:Sample<string>
        class Sample<T> where T : IDisposable { }//有效:Sample<Stream>(引用轉換)
                                                //無效:Sample<string>
        class Sample<T> where T : IComparable<T> { }//有效:Sample<int>(裝箱轉換)
                                                //無效:Sample<FileInfo>
        class Sample<T,U> where T : U { }//有效:Sample<Stream,IDisposable>(引用轉換)
                                         //無效:Sample<string,IDisposable>