六、泛型派生约束
当一个泛型类强制它的一个泛型参数来源于一个接口时,客户端可以为这个类型参数提供一个该接口的具体实现:
public class ListClient<L, T> where L : IList<T>
{
public void ProcessList(L list)
{...}
}
public class NumberList : IList<int>
{...}
ListClient<NumberList,int> client=new ListClient<NumberList,int>();
NumberList numbers=new NumberList();
client.ProcessList(numbers);
但是,可以同样通过指定一个接口类型参数来满足约束,而不是它的一个具体实现:
public class List<T>:IList<T>
{...}
ListClient<IList<int>,int> client=new ListClient<IList<int>,int>();
IList<int> numbers = new List<int>();
client.ProcessList(numbers);
或者可以这样替代:
public class AnotherClient<U>
{
ListClient<IList<U>,U> m_listClient;
}
这样有助于把客户端代码从具体实现中分离出来。
七、泛型,接口和转换
C#编译器只允许把泛型类型参数隐式转换为object,或者是约束规定的类型,这都是类型安全的:
public interface ISomeInterface
{...}
public class BaseClass
{...}
public class MyClass<T> where T:BaseClass,ISomeInterface
{
void SomeMethod(T t)
{
ISomeInterface obj1 = t;
BaseClass obj2 = t;
object obj3 = t;
}
}
编译器允许把泛型类型参数显式转换为其他接口,而不可以是类:
public class MyClass<T>
{
void SomeMethod(T t)
{
ISomeInterface obj = (ISomeInterface)t; //通过编译
BaseClass obj2 = (BaseClass)t; //不会通过编译
}
}
显式转换是危险的,因为它可能会在运行过程中显式转换失败时抛出异常。一个更好的方法就是使用is和as操作符(可参阅:《Programming .Net Components》学习笔记(二)),这里再记一下is的用法:
public interface IMyInterface
{...}
public interface ISomeInterface<T>
{...}
public class MyClass<T>
{
public void MyMothod(T t)
{
if (t is IMyInterface)
{...}
if (t is ISomeInterface<T>)
{...}
}
}
八、泛型接口方法
C# 2.0接口方法也可以定义泛型类型参数,用来指定具体的执行范围:
public interface IMyInterface<T>
{
void MyMethod<X>(T t, X x);
}
这是一个十分重要的功能,它允许可以随时用不同的类型来调用方法,对于多用途类来说是十分方便的。即使是非泛型接口也可以定义泛型方法,这是方法独有的能力。属性和索引器只能在接口定义。当调用一个定义了泛型类型参数的接口方法时,就可以在调用点上提供特定类型:
public interface IMyInterface
{
void MyMethod<X>(T t, X x);
}
public class MyClass : IMyInterface
{
public void MyMehod<T>(T t)
{...}
}
IMyInterface obj = new MyClass();
obj.MyMethod<int>(3);
另外,当方法被请求时,C#编译器可以根据传入的参数类型足够智能地推理得到正确的类型,所以可以不指定特定的类型:
IMyInterface obj = new MyClass();
obj.MyMethod(3);
这种功能被称作“generic type inference(泛型类型推理)”。需要注意的是编译器不能单独基于返回值的类型来推理:
public interface IMyInterface
{
T MyMethod<T>();
}
public class MyClass : IMyInterface
{
public T MyMethod<T>()
{...}
}
IMyInterface obj = new MyClass();
int number = obj.MyMethod(); //不会通过编译
当一个接口方法定义自己独有的泛型类型参数时,也可以定义类型约束。但是,建议最好不要把在接口级的约束扩展到方法级的范例类型参数。
泛型与接口部分结束,泛型可以使接口更加灵活的应用,小心设置约束,不要时接口依赖于具体的实现或者是类型,注意类型安全。
蓝色文字原文,请朋友们帮忙指正翻译一下:
However,you can also satisfy the constraint by specifying as a type parameter the very interface the type parameter is constrained against,not a particular implementation of it
根据原版英文翻译总结的,所以不足和错误之处请大家不吝指正,谢谢:)