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、委托也可以定义自己的泛型参数

C#代码 
  1. 1.泛型和泛型强制转换  
  2.   
  3.  using System;  
  4.  using System.Collections.Generic;  
  5.  using System.Text;  
  6.    
  7.  namespace VS2005Demo2  
  8.  6{  
  9.  7  
  10.  8    C# 编译器只允许将泛型参数隐式强制转换到 Object 或约束指定的类型#region  C# 编译器只允许将泛型参数隐式强制转换到 Object 或约束指定的类型  
  11.  9    public interface ISomeInterface  
  12. 10    { }  
  13. 11    class BaseClass  
  14. 12    { }  
  15. 13    class MyClass<T> where T : BaseClass, ISomeInterface  
  16. 14    {  
  17. 15        void SomeMethod(T t)  
  18. 16        {  
  19. 17            ISomeInterface obj1 = t;  
  20. 18            BaseClass obj2 = t;  
  21. 19            object obj3 = t;  
  22. 20        }  
  23. 21    }  
  24. 22    #endregion  
  25. 23  
  26. 24    编译器允许您将泛型参数显式强制转换到其他任何接口,但不能将其转换到类#region 编译器允许您将泛型参数显式强制转换到其他任何接口,但不能将其转换到类  
  27. 25    class SomeClass  
  28. 26    { }  
  29. 27    //class MyClass1<T>  
  30. 28    //{  
  31. 29    //    void SomeMethod(T t)  
  32. 30    //    {  
  33. 31    //        ISomeInterface obj1 = (ISomeInterface)t;  //Compiles  
  34. 32    //        SomeClass obj2 = (SomeClass)t;           //Does not compile  
  35. 33    //    }  
  36. 34    //}  
  37. 35    #endregion  
  38. 36  
  39. 37  
  40. 38    使用临时的 Object 变量,将泛型参数强制转换到其他任何类型#region 使用临时的 Object 变量,将泛型参数强制转换到其他任何类型  
  41. 39    class MyClass2<T>  
  42. 40    {  
  43. 41        void SomeMethod(T t)  
  44. 42        {  
  45. 43            object temp = t;  
  46. 44            SomeClass obj = (SomeClass)temp;  
  47. 45        }  
  48. 46    }  
  49. 47    #endregion  
  50. 48  
  51. 49    使用isas运算符#region 使用isas运算符  
  52. 50    public class MyClass3<T>  
  53. 51    {  
  54. 52        public void SomeMethod(T t)  
  55. 53        {  
  56. 54            if (t is int) { }  
  57. 55            if (t is LinkedList<intstring>) { }  
  58. 56            string str = t as string;  
  59. 57            if (str != null) { }  
  60. 58            LinkedList<intstring> list = t as LinkedList<intstring>;  
  61. 59            if (list != null) { }  
  62. 60        }  
  63. 61    }  
  64. 62    #endregion  
  65. 63  
  66. 64}  
  67. 65  
  68.   
  69. 2.继承和泛型  
  70.   
  71.   1using System;  
  72.   2using System.Collections.Generic;  
  73.   3using System.Text;  
  74.   4  
  75.   5namespace VS2005Demo2  
  76.   6{  
  77.   7    继承和泛型#region 继承和泛型  
  78.   8    public class BaseClass<T>  
  79.   9    { }  
  80.  10    public class SubClass : BaseClass<int>  
  81.  11    { }  
  82.  12  
  83.  13  
  84.  14    public class SubClass1<R> : BaseClass<R>  
  85.  15    { }  
  86.  16    #endregion  
  87.  17  
  88.  18    继承约束#region 继承约束  
  89.  19    public class BaseClass1<T> where T : ISomeInterface  
  90.  20    { }  
  91.  21    public class SubClass2<T> : BaseClass1<T> where T : ISomeInterface  
  92.  22    { }  
  93.  23  
  94.  24    //构造函数约束  
  95.  25    public class BaseClass3<T> where T : new()  
  96.  26    {  
  97.  27        public T SomeMethod()  
  98.  28        {  
  99.  29            return new T();  
  100.  30        }  
  101.  31    }  
  102.  32    public class SubClass3<T> : BaseClass3<T> where T : new()  
  103.  33    { }  
  104.  34  
  105.  35    #endregion  
  106.  36  
  107.  37    虚拟方法#region 虚拟方法  
  108.  38    public class BaseClass4<T>  
  109.  39    {  
  110.  40        public virtual T SomeMethod()  
  111.  41        {  
  112.  42            return default(T);  
  113.  43        }  
  114.  44    }  
  115.  45    public class SubClass4 : BaseClass4<int>  
  116.  46    {  
  117.  47        public override int SomeMethod()  
  118.  48        {  
  119.  49            return 0;  
  120.  50        }  
  121.  51    }  
  122.  52  
  123.  53    public class SubClass5<T> : BaseClass4<T>  
  124.  54    {  
  125.  55        public override T SomeMethod()  
  126.  56        {  
  127.  57            return default(T);  
  128.  58        }  
  129.  59    }  
  130.  60  
  131.  61    #endregion  
  132.  62  
  133.  63    接口、抽象类继承#region 接口、抽象类继承  
  134.  64    public interface ISomeInterface6<T>  
  135.  65    {  
  136.  66        T SomeMethod(T t);  
  137.  67    }  
  138.  68    public abstract class BaseClass6<T>  
  139.  69    {  
  140.  70        public abstract T SomeMethod(T t);  
  141.  71    }  
  142.  72    public class SubClass6<T> : BaseClass6<T>,ISomeInterface6<T>  
  143.  73    {  
  144.  74        public override T SomeMethod(T t)  
  145.  75        { return default(T); }  
  146.  76    }  
  147.  77    #endregion  
  148.  78  
  149.  79    泛型抽象方法和泛型接口#region 泛型抽象方法和泛型接口  
  150.  80    //public class Calculator<T>  
  151.  81    //{  
  152.  82    //    public T Add(T arg1, T arg2)  
  153.  83    //    {  
  154.  84    //        return arg1 + arg2;//Does not compile   
  155.  85    //    }  
  156.  86    //    //Rest of the methods   
  157.  87    //}  
  158.  88  
  159.  89    public abstract class BaseCalculator<T>  
  160.  90    {  
  161.  91        public abstract T Add(T arg1, T arg2);  
  162.  92        //public abstract T Subtract(T arg1, T arg2);  
  163.  93        //public abstract T Divide(T arg1, T arg2);  
  164.  94        //public abstract T Multiply(T arg1, T arg2);  
  165.  95    }  
  166.  96    public class MyCalculator : BaseCalculator<int>  
  167.  97    {  
  168.  98        public override int Add(int arg1, int arg2)  
  169.  99        {  
  170. 100            return arg1 + arg2;  
  171. 101        }  
  172. 102        //Rest of the methods   
  173. 103    }  
  174. 104  
  175. 105    public interface ICalculator<T>  
  176. 106    {  
  177. 107        T Add(T arg1, T arg2);  
  178. 108        //Rest of the methods   
  179. 109    }  
  180. 110    public class MyCalculator1 : ICalculator<int>  
  181. 111    {  
  182. 112        public int Add(int arg1, int arg2)  
  183. 113        {  
  184. 114            return arg1 + arg2;  
  185. 115        }  
  186. 116        //Rest of the methods   
  187. 117    }  
  188. 118    #endregion  
  189. 119  
  190. 120}  
  191. 121  
  192.   
  193. 3.泛型方法  
  194.   
  195.   1using System;  
  196.   2using System.Collections.Generic;  
  197.   3using System.Text;  
  198.   4  
  199.   5namespace VS2005Demo2  
  200.   6{  
  201.   7  
  202.   8    泛型方法#region 泛型方法  
  203.   9    public class MyClass  
  204.  10    {  
  205.  11        public void MyMethod<T>(T t)  
  206.  12        { }  
  207.  13    }  
  208.  14  
  209.  15    public class Class3  
  210.  16    {  
  211.  17        public void Test()  
  212.  18        {  
  213.  19            MyClass obj = new MyClass();  
  214.  20            obj.MyMethod<int>(3);  
  215.  21  
  216.  22            obj.MyMethod(3);  
  217.  23        }  
  218.  24    }  
  219.  25    #endregion  
  220.  26  
  221.  27    编译器无法只根据返回值的类型推断出类型#region 编译器无法只根据返回值的类型推断出类型  
  222.  28    public class MyClass1  
  223.  29    {  
  224.  30        public T MyMethod<T>()  
  225.  31        { return default(T); }  
  226.  32    }  
  227.  33  
  228.  34    public class Class31  
  229.  35    {  
  230.  36        public void Test()  
  231.  37        {  
  232.  38  
  233.  39            MyClass1 obj = new MyClass1();  
  234.  40            int number = obj.MyMethod<int>();  
  235.  41        }  
  236.  42    }  
  237.  43    #endregion  
  238.  44  
  239.  45    泛型方法约束#region 泛型方法约束  
  240.  46    public class Class32  
  241.  47    {  
  242.  48        public T MyMethod<T>(T t) where T : IComparable<T>  
  243.  49        { return default(T); }  
  244.  50    }  
  245.  51    #endregion  
  246.  52  
  247.  53    泛型虚拟方法#region 泛型虚拟方法  
  248.  54    public class BaseClass33  
  249.  55    {  
  250.  56        public virtual void SomeMethod<T>(T t)  
  251.  57        { }  
  252.  58    }  
  253.  59    public class SubClass33 : BaseClass33  
  254.  60    {  
  255.  61        public override void SomeMethod<T>(T t)  
  256.  62        {  
  257.  63            base.SomeMethod<T>(t);  
  258.  64        }  
  259.  65    }  
  260.  66  
  261.  67    public class BaseClass34  
  262.  68    {  
  263.  69        public virtual void SomeMethod<T>(T t) where T : new()  
  264.  70        { }  
  265.  71    }  
  266.  72    public class SubClass34 : BaseClass34  
  267.  73    {  
  268.  74        public override void SomeMethod<T>(T t)// where T : IComparable<T>  
  269.  75        { }  
  270.  76    }  
  271.  77  
  272.  78    public class BaseClass35  
  273.  79    {  
  274.  80        public virtual void SomeMethod<T>(T t)  
  275.  81        { }  
  276.  82    }  
  277.  83    public class SubClass35 : BaseClass35  
  278.  84    {  
  279.  85        public override void SomeMethod<T>(T t)  
  280.  86        {  
  281.  87            base.SomeMethod<T>(t);  
  282.  88            base.SomeMethod(t);  
  283.  89        }  
  284.  90    }  
  285.  91    #endregion  
  286.  92  
  287.  93    泛型静态方法#region 泛型静态方法  
  288.  94    public class MyClass36<T>  
  289.  95    {  
  290.  96        public static T SomeMethod(T t)  
  291.  97        { return default(T); }  
  292.  98    }  
  293.  99  
  294. 100    public class Class36  
  295. 101    {  
  296. 102        public void Test()  
  297. 103        {  
  298. 104            int number = MyClass36<int>.SomeMethod(3);  
  299. 105        }  
  300. 106    }  
  301. 107  
  302. 108    public class MyClass37<T>  
  303. 109    {  
  304. 110        public static T SomeMethod<X>(T t, X x)  
  305. 111        { return default(T); }  
  306. 112    }  
  307. 113    public class Class37  
  308. 114    {  
  309. 115        public void Test()  
  310. 116        {  
  311. 117            int number = MyClass37<int>.SomeMethod<string>(3, "AAA");  
  312. 118            int number1 = MyClass37<int>.SomeMethod(3, "AAA");  
  313. 119        }  
  314. 120    }  
  315. 121  
  316. 122    public class MyClass38  
  317. 123    {  
  318. 124        public static T SomeMethod<T>(T t) where T : IComparable<T>  
  319. 125        {  return default(T); }  
  320. 126    }  
  321. 127  
  322. 128    #endregion  
  323. 129}  
  324. 130  
  325.   
  326. 4.泛型委托  
  327.   
  328.  1using System;  
  329.  2using System.Collections.Generic;  
  330.  3using System.Text;  
  331.  4  
  332.  5namespace VS2005Demo2  
  333.  6{  
  334.  7    泛型委托#region 泛型委托  
  335.  8    public class MyClass40<T>  
  336.  9    {  
  337. 10        public delegate void GenericDelegate(T t);  
  338. 11        public void SomeMethod(T t)  
  339. 12        { }  
  340. 13    }  
  341. 14  
  342. 15    public class MyClassTest40  
  343. 16    {  
  344. 17        public void Tests()  
  345. 18        {  
  346. 19            MyClass40<int> obj = new MyClass40<int>();  
  347. 20            MyClass40<int>.GenericDelegate del;  
  348. 21  
  349. 22            del = new MyClass40<int>.GenericDelegate(obj.SomeMethod);  
  350. 23            del(3);  
  351. 24  
  352. 25            //委托推理  
  353. 26            del = obj.SomeMethod;  
  354. 27  
  355. 28        }  
  356. 29    }  
  357. 30    #endregion  
  358. 31  
  359. 32    委托泛型参数#region 委托泛型参数  
  360. 33    public class MyClass41<T>  
  361. 34    {  
  362. 35        public delegate void GenericDelegate<X>(T t, X x);  
  363. 36    }  
  364. 37  
  365. 38    //外部委托  
  366. 39    public delegate void GenericDelegate<T>(T t);  
  367. 40  
  368. 41    public class MyClass42  
  369. 42    {  
  370. 43        public void SomeMethod(int number)  
  371. 44        { }  
  372. 45    }  
  373. 46  
  374. 47    public class MyClassTest42  
  375. 48    {  
  376. 49        public void Test()  
  377. 50        {  
  378. 51            MyClass42 obj = new MyClass42();  
  379. 52            GenericDelegate<int> del;  
  380. 53            //del = new GenericDelegate<int>(obj.SomeMethod);  
  381. 54  
  382. 55            del = obj.SomeMethod;  
  383. 56            del(3);  
  384. 57  
  385. 58        }  
  386. 59    }  
  387. 60  
  388. 61    #endregion  
  389. 62  
  390. 63    委托泛型参数#region 委托泛型参数  
  391. 64    public delegate void MyDelegate<T>(T t) where T : IComparable<T>;  
  392. 65    #endregion  
  393. 66  
  394. 67    事件#region 事件  
  395. 68  
  396. 69    public delegate void GenericEventHandler<S, A>(S sender, A args);  
  397. 70      
  398. 71    public class MyPublisher  
  399. 72    {  
  400. 73        public event GenericEventHandler<MyPublisher, EventArgs> MyEvent;  
  401. 74        public void FireEvent()  
  402. 75        {  
  403. 76            MyEvent(this, EventArgs.Empty);  
  404. 77        }  
  405. 78    }  
  406. 79  
  407. 80    public class MySubscriber<A> //Optional: can be a specific type  
  408. 81    {  
  409. 82        public void SomeMethod(MyPublisher sender, A args)  
  410. 83        { }  
  411. 84    }  
  412. 85    public class MyClassTest43  
  413. 86    {  
  414. 87        public void Test()  
  415. 88        {  
  416. 89            MyPublisher publisher = new MyPublisher();  
  417. 90            MySubscriber<EventArgs> subscriber = new MySubscriber<EventArgs>();  
  418. 91            publisher.MyEvent += subscriber.SomeMethod;  
  419. 92        }  
  420. 93    }  
  421. 94    #endregion  
  422. 95}  

原文地址:https://www.cnblogs.com/Leo_wl/p/1893814.html