泛型的定义与使用
1. 泛型的定义
2. 泛型类型参数的使用
定义:只有当方法具有它自己的类型参数列表时,才能称其为泛型方法。
1.1 代码
/// <summary>
/// T 作为myGeneric类型参数
/// </summary>
/// <typeparam name="T"></typeparam>
public class myGeneric<T>
{
/// <summary>
/// 类型T参数作为字段的类型
/// </summary>
public T PropertyA
{
get;
set;
}
/// <summary>
/// 类型参数T作为方法的参数类型与返回值类型
/// </summary>
/// <param name="a"></param>
/// <returns></returns>
public T GetA(T a)
{
return a;
}
/// <summary>
/// 类型参数T作为方法的类型参数列表
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="a"></param>
/// <returns></returns>
public T GetB<T>(T a)
{
return a;
}
}
1.2 类型参数的属性说明
l 类型参数可以作为属性的类型
l 类型参数可以作为方法的返回类型
l 类型参数可以作为方法的参数类型
l 类型参数可以作为方法的类型参数列表
其中GetB<T>(T a) 是泛型方法,因为具有方法的类型参数<T>.
GetA(T a)不是泛型方法,方法没有类型参数,只有参数的类型。
泛型术语
l 泛型类型定义
l 泛型类型参数
Node<T>
l 构造泛型类型
l 泛型类型参数
l 约束
l 泛型方法定义
public class myGeneric<T>
{
public T GetB<T>(T a)
{
return a;
}
}
l 开放类型与封闭类型
Node<int> 封闭类型;
Node<T> 开放类型;
约束
约束定义:
在定义泛型类时,可以对客户端代码能够在实例化类时用于类型参数的类型种类施加限制。如果客户端代码尝试使用某个约束所不允许的类型来实例化类,则会产生编译时错误。这些限制称为约束。约束是使用 where 上下文关键字指定的。
约束的分类示例:
分类:
名称 | 约束 | 说明 |
1 | T:class X | 类型参数必须是引用类型 |
2 | T: struct X | 类型参数必须是非null的值类型。 此约束并不是T必须继承结构体的类型 |
3 | T:基类名X | 类型参数必须是继承基类的类型 |
4 | T:Interface IX | 类型参数必须是实现IX的类型 |
5 | T:U | 类型参数必须是给出的类型或派生自U的类型 |
6 | T:new () | 类型参数必须是具有构造参数的类型 |
7 | 组合上面几种约束 | 约束本身也可以是泛型 |
示例:
约束1:
l 定义:
public class myA<T> where T :class
{
}
l 调用:
static void TestGenericRestrict()
{
//myA<int> myInt = new myA<int>();
//类型“int”必须是引用类型才能用作泛型类型或方法“GenericApp.myA<T>”中的参数“T”
myA<string> myString = new myA<string>();
}
约束2 :
l 定义:
public class myB<T> where T : struct
{
}
l 调用:
static void TestGenericRestrict2()
{
myB<int> myInt = new myB<int>();
//myB<string> myString = new myB<string>();
//类型“string”必须是不可以为 null 值的类型才能用作泛型类型或方法“GenericApp.myB<T>”中的参数“T”
}
约束3
l 定义:
public class myStudent
{
public string Name
{
get;
set;
}
}
public class myC<T> where T : myStudent
{
public T FormatName(T a)
{
a.Name = string.Format("Name:{0}",a.Name );
return a;
}
}
l 调用:
static void TestGenericRestrict3()
{
myC<myStudent> myCStudent = new myC<myStudent>();
Console .WriteLine ( myCStudent.FormatName(new myStudent (){Name="AAAa"}).Name );
}
约束4:
定义:
public class myD<T> where T : IComparable
{
}
调用:
static void TestGenericRestrict4()
{
myD<string> myD = new myD<string>();
//myD<myStudent> myDStudent = new myD<myStudent>();
//不能将类型“GenericApp.myStudent”用作泛型类型或方法“GenericApp.myD<T>”中的类型形参“T”。没有从“GenericApp.myStudent”到“System.IComparable”的隐式引用转换。 E
}
约束5:
定义:
public class myE1
{
}
public class myE2:myE1
{
}
public class myE<T,U> where T : U
{
}
调用:
static void TestGenericRestrict5()
{
// myE<myF1, myF2> myTest= new myE<myF1, myF2>();
//不能将类型“GenericApp.myF1”用作泛型类型或方法“GenericApp.myE<T,U>”中的类型形参“T”。没有从“GenericApp.myF1”到“GenericApp.myF2”的隐式引用转换。
myE<myE2, myE1> myTest2 = new myE<myE2, myE1>();
}
约束6:
public class myF1
{
public myF1()
{
}
}
public class myF2
{
}
public class myF<T> where T : new()
{
public T GetNewItem()
{
return new T();
}
}
定义:
public class myF1
{
public myF1()
{
}
}
public class myF2
{
}
public class myF<T> where T : new()
{
public T GetNewItem()
{
return new T();
}
}
调用:
static void TestGenericRestrict6()
{
myF<myF1> myFF1 = new myF<myF1>();
myFF1.GetNewItem();
myF<myF2> myFF2 = new myF<myF2>();
myFF2.GetNewItem();
myF2 g = new myF2();
//由于编译器自动添加无参构造函数,所以myFF2 也能编译通过
}
约束7:
定义:
public class myG<T> where T:myA<T> ,IComparable<T>,new()
{
}
调用: