泛型类,泛型方法,泛型属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyClass<T>
{
//指定MyMethod方法用以执行类型为X的参数
public void MyMethod<X>(X x)
{
//
}

//此方法也可不指定方法参数
public void MyMethod<X>()
{
//
}
}

MyClass是一个泛型类。

即使类不是泛型类,也可以定义泛型方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyClass
{
//指定MyMethod方法用以执行类型为X的参数
public void MyMethod<X>(X x)
{
//
}

//此方法也可不指定方法参数
public void MyMethod<X>()
{
//
}
}

属性不能指定自己的泛型参数,它们只能使用所属类中定义的泛型参数进行操作。

1
2
3
4
public class MyClass<T>
{
private T _tValue;
}

泛型类的实例化

1
var myClass=new MyClass<int>();

在调用泛型方法的时候,可以提供要在调用场所使用的类型

1
2
3
 //调用泛型方法
MyClass myClass = new MyClass();
myClass.MyMethod<int>(3);

在调用泛型方法时,C#编译器足够聪明,基于传入的参数类型来推断出正确的类型

1
2
3
 //泛型推理机制调用泛型方法
MyClass myClass = new MyClass();
myClass.MyMethod(3);

泛型方法无法只根据返回值的类型推断出类型

1
2
3
4
5
public  static T GetValue<T>()
{
T a =default(T);
return a;
}

1
2
GetValue<int>();
GetValue();//报错

泛型约束

T:struct

类型参数必须是值类型。可以指定除 Nullable 以外的任何值类型。

T:class

类型参数必须是引用类型,包括任何类、接口、委托或数组类型。

T:new()

类型参数必须具有无参数的公共构造函数。当与其他约束一起使用时,new() 约束必须最后指定。

T:<基类名>

类型参数必须是指定的基类或派生自指定的基类。

T:<接口名称>

类型参数必须是指定的接口或实现指定的接口。可以指定多个接口约束。约束接口也可以是泛型的。

T:U

为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。这称为裸类型约束。

泛型方法中泛型参数的约束

1
2
3
4
public T GetTValue<T>(T t)where T:IList
{
return t;
}

类型T必须是IList类型的

1
GetTValue(new List<int>(){1212})

无法为类级别的泛型参数提供方法级别的约束

1
2
3
4
5
6
7
8
public class MyClass<T>
{

public void MyMethod<X>(X x,T t) where X:IComparable<X> where T:IComparer<T>
{
//
}
}

类实例化的时候,T类型已经确定,方法处无法再进行约束,正确的方法

1
2
3
4
5
6
7
8
public class MyClass<T> where T:IComparable<T>
{

public void MyMethod<X>(X x,T t) where X:IComparable<X>
{
//
}
}

泛型参数虚方法的重写:子类方法必须重新定义该方法特定的泛型参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyBaseClass
{
public virtual void SomeMethod<T>(T t)
{
//
}
}
public class MyClass :MyBaseClass
{
public override void SomeMethod<X>(X x)
{

}
}

同时子类中的泛型方法不能重复基类泛型方法的约束

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class MyBaseClass
{
public virtual void SomeMethod<T>(T t) where T:new()
{
//
}
}
public class MyClass :MyBaseClass
{
//正确写法
public override void SomeMethod<X>(X x)
{

}

////错误 重写和显式接口实现方法的约束是从基方法继承的,因此不能直接指定这些约束
//public override void SomeMethod<X>(X x) where X:new()
//{

//}
}

类中定义的委托可以使用该类的泛型参数

1
2
3
4
5
6
7
8
public class MyClass<T>
{
public delegate void GenericDelegate(T t);
public void SomeMethod(T t)
{

}
}

用作约束的泛型类型参数称为裸类型约束

1
2
3
4
class List<T>
{
void Add<U>(List<U> items) where U : T {/*...*/}
}