泛型类型的约束
所谓的泛型类型约束,实际上就是约束的类型T。使T必须遵循一定的规则。比如T必须继承自某个类,或者T必须实现某个接口等等。那么怎么给泛型指定约束?其实也很简单,只需要where关键字。加上约束的条件。
约束条件有以下
where T : struct -类型T必须是值类型
where T : class -类型T必须是引用类型
where T : Ifoo -类型T必须执行接口Ifoo
where T : foo -类型T必须继承自 foo
where T : new() -类型T必须有一个默认构造函数
where T : U -指定泛型类型T1派生于T2。
下面我会解释每个约束该怎么用,使用约束不单单可以限制T,而且还可以使T具有类型可用性,上面我们介绍了,我们只有在实例化的时候才替换泛型类型,所以我们除了能把泛型转换为object外,基本上在定义的时候不能与其他类型做任何交互,如果这里我约束泛型T实现了接口IFoo,那么我们就可以把泛型转换为IFoo,从而使用Ifoo里定义的方法。这样就使类型在定义的时候就可以使用,而不需要等到实例化。
而指定T的类型是非常简单的。
public class Person<T>where T:struct
这时,如果我们使用引用类型替换T就会编译出错。我们也可以约束T为引用类型,这里写一个例子,怎么使约束为接口和基类型,然后使用这些类型:
class Program
{
static void Main(string[] args)
{
MyID myId = new MyID("北京", "清华", "15级", "007");
Person<MyID> perosn = new Person<MyID>(myId, "小明", "王");
DisPerson<Person<MyID>> dis = new DisPerson<Person<MyID>>(perosn);
dis.dis();
}
//定义接口
public interface IPerson
{
void DisplayPerosnWithOutId();
void DisplayPerosnWithId();
}
public class MyID
{
private string _city;
public string City
{
get { return _city; }
set { _city = value; }
}
private string _school;
public string School
{
get { return _school; }
set { _school = value; }
}
private string _className;
public string ClassName
{
get { return _className; }
set { _className = value; }
}
private string _number;
public string Number
{
get { return _number; }
set { _number = value; }
}
public MyID() { }
public MyID(string city, string school, string className, string number)
{
this._city = city;
this._school = school;
this._className = className;
this._number = number;
}
}
//这里让我们的Perosn实现这个接口,然后我们的Perosn里面的泛型T必须是继承自MyId的。注意,这里
//约束的是我们的Person的T
public class Person<T> : IPerson where T : MyID
{
private T _t;
public T T1
{
get { return _t; }
set { _t = value; }
}
private string _firstName;
public string FirstName
{
get { return _firstName; }
set { _firstName = value; }
}
private string _lastName;
public string LastName
{
get { return _lastName; }
set { _lastName = value; }
}
public Person() { }
public Person(T t1, string firstName, string lastName)
{
this._t = t1;
this._firstName = firstName;
this._lastName = lastName;
}
public void DisplayPerosnWithOutId()
{
Console.WriteLine("名字:{0},姓:{1}", FirstName, LastName);
}
public void DisplayPerosnWithId()
{
MyID myId = T1;
Console.WriteLine("ID:{0},名字:{1},姓:{2}", myId.City + "-" + myId.School + "-" + myId.ClassName + "-" + myId.Number, FirstName, LastName);
}
}
//这里就是我们的泛型类,这个类的约束是T必须实现IPerson。所以T就可以跟IPerson实现转换,从而调
//用IPerosn里调用的方法。
public class DisPerson<T> where T : IPerson
{
private T t { get; set; }
public DisPerson() { }
public DisPerson(T t1)
{
this.t = t1;
}
public void dis()
{
IPerson p = (IPerson)t;
p.DisplayPerosnWithId();
p.DisplayPerosnWithOutId();
}
}
}