C# 泛型約束 xxx Where T:約束(二)

來源:互聯網
上載者:User

標籤:style   blog   http   使用   資料   2014   ar   代碼   

接著上篇的,通過以上的具體使用執行個體:

所謂泛型,即通過參數化型別來實現在同一份代碼上操作多種資料類型,泛型程式設計是一種編程範式,它利用“參數化型別”將類型抽象化,從而實現更為靈活的複用。

在定義泛型類時,可以對用戶端代碼能夠在執行個體化類時用於型別參數的類型種類施加限制。如果用戶端代碼嘗試使用某個約束所不允許的類型來執行個體化類,則會產生編譯時間錯誤。這些限制稱為約束。約束是使用 where 內容關鍵字指定的。

下表列出了五種類型的約束:

約束 說明
T:struct 型別參數必須是實值型別。可以指定除 Nullable 以外的任何實值型別。
T:class 型別參數必須是參考型別,包括任何類、介面、委託或數群組類型。
T:new () 型別參數必須具有無參數的公用建構函式。當與其他約束一起使用時,new() 約束必須最後指定。
T:<基類名> 型別參數必須是指定的基類或派生自指定的基類。
T:<介面名稱> 型別參數必須是指定的介面或實現指定的介面。可以指定多個介面約束。約束介面也可以是泛型的。
T:U 為 T 提供的型別參數必須是為 U 提供的參數或派生自為 U 提供的參數。這稱為裸類型約束.
一.派生約束

1.常見的

public class MyClass5<T> where T :IComparable { }

2.約束放在類的實際派生之後

public class B { }

public class MyClass6<T> : B where T : IComparable { }

3.可以繼承一個基類和多個介面,且基類在介面前面

public class B { }

public class MyClass7<T> where T : B, IComparable, ICloneable { } 二.建構函式約束

1.常見的

public class MyClass8<T> where T :  new() { }

2.可以將建構函式約束和派生約束組合起來,前提是建構函式約束出現在約束列表的最後

public class MyClass8<T> where T : IComparable, new() { } 三.值約束

1.常見的

public class MyClass9<T> where T : struct { }

2.與介面約束同時使用,在最前面(不能與基類約束,建構函式約束一起使用)

public class MyClass11<T> where T : struct, IComparable { } 四.參考條件約束

1.常見的

public class MyClass10<T> where T : class { } 五.多個泛型參數

public class MyClass12<T, U> where T : IComparable  where U : class { } 六.繼承和泛型

public class B<T>{ }

1. 在從泛型基類派生時,可以提供類型實參,而不是基類泛型參數

    public class SubClass11 : B<int>
    { }

2.如果子類是泛型,而非具體的類型實參,則可以使用子類泛型參數作為泛型基類的指定類型

    public class SubClass12<R> : B<R>
    { }

3.在子類重複基類的約束(在使用子類泛型參數時,必須在子類層級重複在基類層級規定的任何約束)
    public class B<T> where T : ISomeInterface { }
    public class SubClass2<T> : B<T> where T : ISomeInterface { }

4.建構函式約束
    public class B<T> where T : new()
    {
        public T SomeMethod()
        {
            return new T();
        }
    }
    public class SubClass3<T> : B<T> where T : new(){ } 七.泛型方法(C#2.0泛型機制支援在"方法聲名上包含型別參數",這就是泛型方法)

1.泛型方法既可以包含在泛型型別中,又可以包含在非泛型型別中

public class MyClass5
    {

        public void MyMethod<T>(T t){ }
    }

2.泛型方法的聲明與調用

public class MyClass5
    {
        public void MyMethod<T>(T t){ }
    }
    public class App5
    {
        public void CallMethod()
        {
            MyClass5 myclass5 = new MyClass5();
            myclass5.MyMethod<int>(3);
        }
    }

3.泛型方法的重載

//第一組重載
void MyMethod1<T>(T t, int i){ }

void MyMethod1<U>(U u, int i){ }

//第二組重載
void MyMethod2<T>(int i){ }
void MyMethod2(int i){ }

//第三組重載,假設有兩個泛型參數
void MyMethod3<T>(T t) where T : A { }
void MyMethod3<T>(T t) where T : B { }

//第四組重載

public class MyClass8<T,U>
    {
        public T MyMothed(T a, U b)
        {
            return a;
        }
        public T MyMothed(U a, T b)
        {
            return b;
        }
        public int MyMothed(int a, int b)
        {
            return a + b;
        }
    }

4.泛型方法的覆寫

(1)public class MyBaseClass1
    {
        public virtual void MyMothed<T>(T t) where T : new() { }
    }
    public class MySubClass1:MyBaseClass1
    {
        public override void MyMothed<T>(T t) //不能重複任何約束
        { }
    }

(2)public class MyBaseClass2
    {
        public virtual void MyMothed<T>(T t)
        { }
    }
    public class MySubClass2 : MyBaseClass2
    {
        public override void MyMothed<T>(T t) //重新定義泛型參數T
        { }
    } 八.虛擬方法

public class BaseClass4<T>
    {
        public virtual T SomeMethod()
        {
            return default(T);
        }
    }
    public class SubClass4 : BaseClass4<int> //使用實參繼承的時候方法要使用實參的類型
    {
        public override int SomeMethod()
        {
            return 0;
        }
    }

    public class SubClass5<T> : BaseClass4<T> //使用泛型繼承時,方法也是泛型
    {
        public override T SomeMethod()
        {
            return default(T);
        }
    } 九.編譯器只允許將泛型參數隱式強制轉換到 Object 或約束指定的類型

class MyClass<T> where T : BaseClass, ISomeInterface
    {
        void SomeMethod(T t)
        {
            ISomeInterface obj1 = t;
            BaseClass obj2 = t;
            object obj3 = t;
        }
    }

變通方法:使用臨時的 Object 變數,將泛型參數強制轉換到其他任何類型

class MyClass2<T>
    {
        void SomeMethod(T t)
        {
            object temp = t;
            BaseClass obj = (BaseClass)temp;
        }
    } 十.編譯器允許您將泛型參數顯式強制轉換到其他任何介面,但不能將其轉換到類

class MyClass1<T>
    {
        void SomeMethod(T t)
        {
            ISomeInterface obj1 = (ISomeInterface)t; 
            //BaseClass obj2 = (BaseClass)t;           //不能通過編譯
        }
    } 十一.使用臨時的 Object 變數,將泛型參數強制轉換到其他任何類型

class MyClass2<T>
    {
        void SomeMethod(T t)
        {
            object temp = t;
            BaseClass obj = (BaseClass)temp;
        }
    } 十二.使用is和as運算子

public class MyClass3<T>
    {
        public void SomeMethod(T t)
        {
            if (t is int) { }
            if (t is LinkedList<int>) { }
            string str = t as string;
            if (str != null) { }
            LinkedList<int> list = t as LinkedList<int>;
            if (list != null) { }
        }
    }

轉載自:http://www.cnblogs.com/andrew-blog/archive/2012/03/21/ListT_Where.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.