泛型
一、什么是泛型?
通过泛型可以定义类型安全类,而不会损害类型安全、性能或工作效率
二、实例化泛型
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 isint) { }
- 55 if (t is LinkedList<int,string>) { }
- 56 string str = t asstring;
- 57 if (str != null) { }
- 58 LinkedList<int,string> list = tas 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 overrideint 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 abstractclass 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 abstractclass 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 overrideint 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 virtualvoid SomeMethod<T>(T t)
- 57 { }
- 58 }
- 59 public class SubClass33 : BaseClass33
- 60 {
- 61 public overridevoid SomeMethod<T>(T t)
- 62 {
- 63 base.SomeMethod<T>(t);
- 64 }
- 65 }
- 66
- 67 public class BaseClass34
- 68 {
- 69 public virtualvoid SomeMethod<T>(T t) where T :new()
- 70 { }
- 71 }
- 72 public class SubClass34 : BaseClass34
- 73 {
- 74 public overridevoid SomeMethod<T>(T t)// where T : IComparable<T>
- 75 { }
- 76 }
- 77
- 78 public class BaseClass35
- 79 {
- 80 public virtualvoid SomeMethod<T>(T t)
- 81 { }
- 82 }
- 83 public class SubClass35 : BaseClass35
- 84 {
- 85 public overridevoid 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 delegatevoid 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 delegatevoid GenericDelegate<X>(T t, X x);
- 36 }
- 37
- 38 //外部委托
- 39 public delegatevoid 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 delegatevoid MyDelegate<T>(T t) where T : IComparable<T>;
- 65 #endregion
- 66
- 67 事件#region 事件
- 68
- 69 public delegatevoid 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}