C#泛型(包括泛型抽象類的繼承)


泛型
一、什么是泛型?
通過泛型可以定義類型安全類,而不會損害類型安全、性能或工作效率

二、實例化泛型
1、可以使用任何類型來聲明和實例化
2、申明和實例話都必須用一個特定的類型來代替一般類型T
3、例子:
//原來寫法
Public class Stack
{
object[] m_Items;
public void Push(object item)
{...}
public object Pop()
{...}
}
Stack stack = new Stack();
stack.Push(1);
int number = (int)stack.Pop();

//有了泛型后
Public class Stack <T>
{
T[] m_Items;
public void Push(T item)
{...}
public T Pop()
{...}
}
Stack <int> stack = new Stack <int> ();
stack.Push(1);
int number = (int)stack.Pop();

三:泛型的好處
1、一次性的開發、測試和部署代碼,通過任何類型來重用它
2、編譯器支持和類型安全
3、不會強行對值類型進行裝箱和取消裝箱,或者對引用類型進行向下強制類型轉換,所以性能得到顯著提高。
注:值類型大概可以提高200%,引用類型大概為100%

四:多個泛型
1、單個類型可以定義多個泛型

五:泛型別名
1、在文件頭部使用using 為特定類型取別名,別名作用范圍是整個文件
2、例子
using List = LinkedList <int,string> ;
class ListClient
{
static void Main(string[] args)
{
List list = new List();
list.AddHead(123, "AAA ");
}
}

五:泛型約束
(1)、派生約束
如:
public class LinkedList <K,T> where K:IComparable
{
T Find(K key)
{
if (str.Key.CompareTo(key) == 0)//只有實現這個接口才可比較
}
}

注意:
1、所有的派生約束必須放在類的實際派生列表之后
如:public class LinkedList <K,T> :IEnumerable <T> where K:IComparable <K>
{...}
2、一個泛型參數上可以約束多個接口(用逗號分隔)
public class LinkedList <K,T> where K:IComparable <K> ,IConvertible
3、在一個約束中最多只能使用一個基類
4、約束的基類不能是密封類或靜態類
5、不能將System.Delegate或System.Array約束為基類
6、可以同時約束一個基類以及一個或多個接口,但是該基類必須首先出現在派生約束列表中。
7、C#允許你將另一個泛型參數指定為約束
public class MyClass <T,U> where T:U
{...}
8、可以自己定義基類或接口進行泛型約束
9、自定義的接口或基類必須與泛型具有一致的可見性

(2)、構造函數約束
如:
class Node <K,T> where T:new()
{
}
注意:
1、可以將構造函數的約束和派生約束結合起來,前提是構造函數的約束出現在約束列表中的最后

(3)、引用/值類型約束
1、可以使用struct約束將泛型參數約束為值類型(如int、bool、enum),或任何自定義結構
2、同樣可以使用class約束將泛型參數約束為引用類型
3、不能將引用/值類型約束與基類約束一起使用,因為基類約束涉及到類
4、不能使用結構和默認構造函數約束,因為默認構造函數約束也涉及到類
5、雖然您可以使用類和默認構造函數約束,但是這樣做沒有任何價值
6、可以將引用/值類型約束與接口約束組合起來,前提是引用/值類型約束出現在約束列表的開頭

六:泛型和強制類型轉換
1、C#編譯器只允許將泛型參數隱式轉換到Object或約束指定的類型
如:
interface IS{...}
class BaseClass{...}
class MyClass <T> where T:BaseClass,IS
{
void SomeMethod(T t)
{
IS obj1 = t;
BaseClass obj2 = t;
object obj3 = t;
}
}
2、編譯器允許你將泛型參數顯示強制轉換到其他任何借口,但不能將其轉換到類
interface IS{...}
class SomeClass{...}
class MyClass <T> //沒有約束
{
void SomeMethod(T t)
{
IS obj1 = (IS)t; //可以
SomeClass obj2 = (SomeClass)t //不可以
}
}
3、可以使用臨時的Object變量,將泛型參數強制轉換到其他任何類型
class SomeClass{...}
class MyClass <T>
{
void SomeMethod(T t)
{
object temp = t;
SomeClass obj = (SomeClass)temp;//可以
}
}
注意:這里只是告訴你這樣寫是可以的,但是要不要這樣寫?不要這樣寫,因為如果t確實沒有繼承SomeClass編譯沒錯但是運行就會出錯
4、解決上面強制轉換問題,可以使用is和as運算符進行判斷
public class MyClass <T>
{
public void SomeMethod <T t>
{
if (t is int ){...}
if (t is LinkedList <int,string> ){...}
//如果泛型參數的類型是所查詢的類型,則is運算符返回true
string str = t as string;
//如果這寫類型兼容,則as將執行強制類型轉換,否則將返回null
if (str != null){...}
LinkedList <int,string> list = t as LinkedList <int,string> ;
if (list != null){...}
}
}

七:繼承和泛型
1、在從泛型基類派生,可以提供類型實參,而不是基類泛型參數
public class BaseClass <T> {...}
public class SubClass:BaseClass <int>
2、如果子類是泛型,而非具體的類型實參,則可以使用子類泛型參數作為泛型基類的指定類型
public class BaseClass <TT> {...}
public class SubClass <T> :BaseClass <T> {...}
3、在使用子類泛型參數時,必須在子類級別重復在基類級別規定的任何約束
4、基類可以定義其簽名使用泛型參數的虛禮方法,在重寫它們時,子類必須在方法簽名中提供相應的類型。
如:
public class BaseClass <T>
{
public virtual T SomeMethod()
{...}
}
public class SubClass:BaseClass <int>
{
public override int SomeMethod()
{...}
}
5、如果該子類是泛型,則它還可以在重寫時使用它自己的泛型參數
public class SubClass <T> :BaseClass <T>
{
public override T SomeMethod()
{...}
}
6、你可以定義泛型接口、泛型抽象類,甚至泛型抽象方法。
7、不能對泛型參數使用+或+=之類的運算符
public class Calculator <T>
{
public T Add (T arg1,T arg2)
{
return arg1 + arg2;//錯誤
}
}
但是我們可以通過泛型抽象類、接口來實現在個功能,因為實現泛型抽象類、接口我們就已經明確傳一個參數了,就可以執行諸如+這樣的操作。

八:泛型方法
1、方法可以定義特定於其執行范圍的泛型參數
public class MyClass <T>
{
public void MyMethod <X> (X x)
{...}
}
2、即使各包含類根本不使用泛型,你也可以定義方法特定的泛型參數
public class MyClass
{
public void MyMethod <T> (T t)
{...}
}
注意:該功能只使用於方法,屬性,索引器只能使用在類的作用范圍中定義的泛型參數。
3、調用泛型方法
MyClass obj = new MyClass();
obj.MyMethod <int> (3);
也可以這樣:
MyClass obj = new MyClass();
obj.MyMethod(3); //該功能稱為泛型推理
4、泛型方法也可以有自己的泛型參數約束
pubic class MyClass
{
public void SomeMethod <T> (T t) where T:IComparable <T>
{...}
}
5、子類方法實現不能重復在父級別出現的約束
public class BaseClass
{
public virtual void SomeMethod <T> (T t)where T:new()
{...}
}
pubic class SubClass:BaseClass
{
public override void SomeMethod <T> (T t)//不能再有約束
{...}
}
6、靜態方法
靜態方法可以定義特定的泛型參數和約束
public class MyClass <T>
{
public static T SomeMethod <X> (T t,X x)
{...}
}
int number = MyClass <int> .SomeMethod <string> (3, "AAA ");
或者:int mumber = MyClass <int> .SomeMethod(3, "AAA ");

九:泛型委托
1、在某個類中定義的委托可以利用該類的泛型參數
2、委托也可以定義自己的泛型參數

1.泛型和泛型強制轉換   
   
 using System;   
 using System.Collections.Generic;   
 using System.Text;   
    
 namespace VS2005Demo2   
 6{   
 7   
 8    C# 編譯器只允許將泛型參數隱式強制轉換到 Object 或約束指定的類型#region  C# 編譯器只允許將泛型參數隱式強制轉換到 Object 或約束指定的類型   
 9    public interface ISomeInterface   
10    { }   
11    class BaseClass   
12    { }   
13    class MyClass<T> where T : BaseClass, ISomeInterface   
14    {   
15        void SomeMethod(T t)   
16        {   
17            ISomeInterface obj1 = t;   
18            BaseClass obj2 = t;   
19            object obj3 = t;   
20        }   
21    }   
22    #endregion   
23   
24    編譯器允許您將泛型參數顯式強制轉換到其他任何接口,但不能將其轉換到類#region 編譯器允許您將泛型參數顯式強制轉換到其他任何接口,但不能將其轉換到類   
25    class SomeClass   
26    { }   
27    //class MyClass1<T>   
28    //{   
29    //    void SomeMethod(T t)   
30    //    {   
31    //        ISomeInterface obj1 = (ISomeInterface)t;  //Compiles   
32    //        SomeClass obj2 = (SomeClass)t;           //Does not compile   
33    //    }   
34    //}   
35    #endregion   
36   
37   
38    使用臨時的 Object 變量,將泛型參數強制轉換到其他任何類型#region 使用臨時的 Object 變量,將泛型參數強制轉換到其他任何類型   
39    class MyClass2<T>   
40    {   
41        void SomeMethod(T t)   
42        {   
43            object temp = t;   
44            SomeClass obj = (SomeClass)temp;   
45        }   
46    }   
47    #endregion   
48   
49    使用is和as運算符#region 使用is和as運算符   
50    public class MyClass3<T>   
51    {   
52        public void SomeMethod(T t)   
53        {   
54            if (t is int) { }   
55            if (t is LinkedList<int, string>) { }   
56            string str = t as string;   
57            if (str != null) { }   
58            LinkedList<int, string> list = t as LinkedList<int, string>;   
59            if (list != null) { }   
60        }   
61    }   
62    #endregion   
63   
64}   
65   
   
2.繼承和泛型   
   
  1using System;   
  2using System.Collections.Generic;   
  3using System.Text;   
  4   
  5namespace VS2005Demo2   
  6{   
  7    繼承和泛型#region 繼承和泛型   
  8    public class BaseClass<T>   
  9    { }   
 10    public class SubClass : BaseClass<int>   
 11    { }   
 12   
 13   
 14    public class SubClass1<R> : BaseClass<R>   
 15    { }   
 16    #endregion   
 17   
 18    繼承約束#region 繼承約束   
 19    public class BaseClass1<T> where T : ISomeInterface   
 20    { }   
 21    public class SubClass2<T> : BaseClass1<T> where T : ISomeInterface   
 22    { }   
 23   
 24    //構造函數約束   
 25    public class BaseClass3<T> where T : new()   
 26    {   
 27        public T SomeMethod()   
 28        {   
 29            return new T();   
 30        }   
 31    }   
 32    public class SubClass3<T> : BaseClass3<T> where T : new()   
 33    { }   
 34   
 35    #endregion   
 36   
 37    虛擬方法#region 虛擬方法   
 38    public class BaseClass4<T>   
 39    {   
 40        public virtual T SomeMethod()   
 41        {   
 42            return default(T);   
 43        }   
 44    }   
 45    public class SubClass4 : BaseClass4<int>   
 46    {   
 47        public override int SomeMethod()   
 48        {   
 49            return 0;   
 50        }   
 51    }   
 52   
 53    public class SubClass5<T> : BaseClass4<T>   
 54    {   
 55        public override T SomeMethod()   
 56        {   
 57            return default(T);   
 58        }   
 59    }   
 60   
 61    #endregion   
 62   
 63    接口、抽象類繼承#region 接口、抽象類繼承   
 64    public interface ISomeInterface6<T>   
 65    {   
 66        T SomeMethod(T t);   
 67    }   
 68    public abstract class BaseClass6<T>   
 69    {   
 70        public abstract T SomeMethod(T t);   
 71    }   
 72    public class SubClass6<T> : BaseClass6<T>,ISomeInterface6<T>   
 73    {   
 74        public override T SomeMethod(T t)   
 75        { return default(T); }   
 76    }   
 77    #endregion   
 78   
 79    泛型抽象方法和泛型接口#region 泛型抽象方法和泛型接口   
 80    //public class Calculator<T>   
 81    //{   
 82    //    public T Add(T arg1, T arg2)   
 83    //    {   
 84    //        return arg1 + arg2;//Does not compile    
 85    //    }   
 86    //    //Rest of the methods    
 87    //}   
 88   
 89    public abstract class BaseCalculator<T>   
 90    {   
 91        public abstract T Add(T arg1, T arg2);   
 92        //public abstract T Subtract(T arg1, T arg2);   
 93        //public abstract T Divide(T arg1, T arg2);   
 94        //public abstract T Multiply(T arg1, T arg2);   
 95    }   
 96    public class MyCalculator : BaseCalculator<int>   
 97    {   
 98        public override int Add(int arg1, int arg2)   
 99        {   
100            return arg1 + arg2;   
101        }   
102        //Rest of the methods    
103    }   
104   
105    public interface ICalculator<T>   
106    {   
107        T Add(T arg1, T arg2);   
108        //Rest of the methods    
109    }   
110    public class MyCalculator1 : ICalculator<int>   
111    {   
112        public int Add(int arg1, int arg2)   
113        {   
114            return arg1 + arg2;   
115        }   
116        //Rest of the methods    
117    }   
118    #endregion   
119   
120}   
121   
   
3.泛型方法   
   
  1using System;   
  2using System.Collections.Generic;   
  3using System.Text;   
  4   
  5namespace VS2005Demo2   
  6{   
  7   
  8    泛型方法#region 泛型方法   
  9    public class MyClass   
 10    {   
 11        public void MyMethod<T>(T t)   
 12        { }   
 13    }   
 14   
 15    public class Class3   
 16    {   
 17        public void Test()   
 18        {   
 19            MyClass obj = new MyClass();   
 20            obj.MyMethod<int>(3);   
 21   
 22            obj.MyMethod(3);   
 23        }   
 24    }   
 25    #endregion   
 26   
 27    編譯器無法只根據返回值的類型推斷出類型#region 編譯器無法只根據返回值的類型推斷出類型   
 28    public class MyClass1   
 29    {   
 30        public T MyMethod<T>()   
 31        { return default(T); }   
 32    }   
 33   
 34    public class Class31   
 35    {   
 36        public void Test()   
 37        {   
 38   
 39            MyClass1 obj = new MyClass1();   
 40            int number = obj.MyMethod<int>();   
 41        }   
 42    }   
 43    #endregion   
 44   
 45    泛型方法約束#region 泛型方法約束   
 46    public class Class32   
 47    {   
 48        public T MyMethod<T>(T t) where T : IComparable<T>   
 49        { return default(T); }   
 50    }   
 51    #endregion   
 52   
 53    泛型虛擬方法#region 泛型虛擬方法   
 54    public class BaseClass33   
 55    {   
 56        public virtual void SomeMethod<T>(T t)   
 57        { }   
 58    }   
 59    public class SubClass33 : BaseClass33   
 60    {   
 61        public override void SomeMethod<T>(T t)   
 62        {   
 63            base.SomeMethod<T>(t);   
 64        }   
 65    }   
 66   
 67    public class BaseClass34   
 68    {   
 69        public virtual void SomeMethod<T>(T t) where T : new()   
 70        { }   
 71    }   
 72    public class SubClass34 : BaseClass34   
 73    {   
 74        public override void SomeMethod<T>(T t)// where T : IComparable<T>   
 75        { }   
 76    }   
 77   
 78    public class BaseClass35   
 79    {   
 80        public virtual void SomeMethod<T>(T t)   
 81        { }   
 82    }   
 83    public class SubClass35 : BaseClass35   
 84    {   
 85        public override void SomeMethod<T>(T t)   
 86        {   
 87            base.SomeMethod<T>(t);   
 88            base.SomeMethod(t);   
 89        }   
 90    }   
 91    #endregion   
 92   
 93    泛型靜態方法#region 泛型靜態方法   
 94    public class MyClass36<T>   
 95    {   
 96        public static T SomeMethod(T t)   
 97        { return default(T); }   
 98    }   
 99   
100    public class Class36   
101    {   
102        public void Test()   
103        {   
104            int number = MyClass36<int>.SomeMethod(3);   
105        }   
106    }   
107   
108    public class MyClass37<T>   
109    {   
110        public static T SomeMethod<X>(T t, X x)   
111        { return default(T); }   
112    }   
113    public class Class37   
114    {   
115        public void Test()   
116        {   
117            int number = MyClass37<int>.SomeMethod<string>(3, "AAA");   
118            int number1 = MyClass37<int>.SomeMethod(3, "AAA");   
119        }   
120    }   
121   
122    public class MyClass38   
123    {   
124        public static T SomeMethod<T>(T t) where T : IComparable<T>   
125        {  return default(T); }   
126    }   
127   
128    #endregion   
129}   
130   
   
4.泛型委托   
   
 1using System;   
 2using System.Collections.Generic;   
 3using System.Text;   
 4   
 5namespace VS2005Demo2   
 6{   
 7    泛型委托#region 泛型委托   
 8    public class MyClass40<T>   
 9    {   
10        public delegate void GenericDelegate(T t);   
11        public void SomeMethod(T t)   
12        { }   
13    }   
14   
15    public class MyClassTest40   
16    {   
17        public void Tests()   
18        {   
19            MyClass40<int> obj = new MyClass40<int>();   
20            MyClass40<int>.GenericDelegate del;   
21   
22            del = new MyClass40<int>.GenericDelegate(obj.SomeMethod);   
23            del(3);   
24   
25            //委托推理   
26            del = obj.SomeMethod;   
27   
28        }   
29    }   
30    #endregion   
31   
32    委托泛型參數#region 委托泛型參數   
33    public class MyClass41<T>   
34    {   
35        public delegate void GenericDelegate<X>(T t, X x);   
36    }   
37   
38    //外部委托   
39    public delegate void GenericDelegate<T>(T t);   
40   
41    public class MyClass42   
42    {   
43        public void SomeMethod(int number)   
44        { }   
45    }   
46   
47    public class MyClassTest42   
48    {   
49        public void Test()   
50        {   
51            MyClass42 obj = new MyClass42();   
52            GenericDelegate<int> del;   
53            //del = new GenericDelegate<int>(obj.SomeMethod);   
54   
55            del = obj.SomeMethod;   
56            del(3);   
57   
58        }   
59    }   
60   
61    #endregion   
62   
63    委托泛型參數#region 委托泛型參數   
64    public delegate void MyDelegate<T>(T t) where T : IComparable<T>;   
65    #endregion   
66   
67    事件#region 事件   
68   
69    public delegate void GenericEventHandler<S, A>(S sender, A args);   
70       
71    public class MyPublisher   
72    {   
73        public event GenericEventHandler<MyPublisher, EventArgs> MyEvent;   
74        public void FireEvent()   
75        {   
76            MyEvent(this, EventArgs.Empty);   
77        }   
78    }   
79   
80    public class MySubscriber<A> //Optional: can be a specific type   
81    {   
82        public void SomeMethod(MyPublisher sender, A args)   
83        { }   
84    }   
85    public class MyClassTest43   
86    {   
87        public void Test()   
88        {   
89            MyPublisher publisher = new MyPublisher();   
90            MySubscriber<EventArgs> subscriber = new MySubscriber<EventArgs>();   
91            publisher.MyEvent += subscriber.SomeMethod;   
92        }   
93    }   
94    #endregion   
95} 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM