三、显式实现泛型接口
与非泛型接口相同,泛型接口也可以显式实现:
public class NumberList : IList<int>
{
void IList<int>.AddHead(int item)
{...}
void IList<int>.RemoveHead(int item)
{...}
void IList<int>.RemoveAll()
{...}
}
需要注意的是显式实现中类型参数的指定。因为,譬如AddHead()方法不仅是泛型接口IList<T>的一个方法,确切地说应是一个类型参数为int的泛型接口方法。同样的,如果实现类本身是一个泛型类,则下边这种实现也是正确的:
public class List<T> : IList<T>
{
void IList<T>.AddHead(T item)
{...}
//Rest of the implementation
}
当要在同一个类型里显式实现泛型类型的多个版本要特别注意,需要实现每个版本的方法:当让也可以隐式实现:
public class List : IList<int>, IList<string>
{
public void AddHead(int item)
{...}
public void AddHead(string item)
{...}
public void RemoveAll()
{...}
}
在这个例子中这样要比使用显式接口继承要好些。因为像RemoveAll()这样的方法可以在同一实现方法中实现IList<int>和IList<string>。客户端对IList<int>,IList<string>都可以调用该方法:
IList<int> list = new List();
list.RemoveAll();
但是,在实现同一泛型接口的多个类型参数版本时,往往不得不使用显式实现,否则会产生二义性。例如,如果IList<T>包含这样一个GetHead()方法:
public interface IList<T>
{
void AddHead(T item);
void RemoveHead(T item);
void RemoveAll();
T GetHead();
}
public class List : IList<int>, IList<string>
{
int IList<int>.GetHead()
{...}
string IList<string>.GetHead()
{...}
// Rest of the implementation
}
四、泛型接口操作符
C#2.0有一个有趣的泛型接口的应用。在C#2.0中不可以对泛型参数使用像+或+=这样的操作符。像下边这样的代码就不会通过编译:
public class Calculator<T>
{
public T Add(T argument1, T argument2)
{
return argument1 + argument2; //不会通过编译
}
//Rest of the methods
}
编译器不会知道客户端指定的类型参数是否支持+操作符,所以拒绝编译。不过那,可以通过使用泛型操作的接口来补偿:
public interface ICalculator<T>
{
T Add(T argument1, T argument2);
T Subtract(T argument1, T argument2);
T Divide(T argument1, T argument2);
T Multiply(T argument1, T argument2);
}
public class Calculator : ICalculator<int>
{
public int Add(int argument1, int argument2)
{
return argument1 + argument2;
}
//Rest of the methods
}
五、接口级约束
一个接口可以定义它使用的泛型类型的约束(where关键字)。例如:
public interface IList<T> where T : IComparable<T>
{...}
这样就得记住在接口范围内定义的约束的实现(IComparable<T>)。但是,一个接口不应当包含任何实现细节,而这样恰恰就违法了分离接口和实现的原则。对类型参数的约束,就会使接口与特定的实现操作耦合。
例如,约束接口上的类型参数来源于一个具体的类,就不是个好做法:
public class Customer
{...}
public interface IList<T> where T:Customer
{...}
这样做,实际上使泛型接口IList<T>只能用来管理Customers列表。如果要在接口级使用强类型实现多态性,应当定义一个新接口来专门管理Customer,以代替对泛型接口IList<T>多用途定义的曲解:
public interface ICustomerList:IList<Customer>
{...}
像下面这样约束一个默认构造器,也是应当避免的:
public interface IList<T> where T:new()
{...}
不是所有类型都有默认公共构造器(例如单件模式),并且接口不会真正关心它们没有构造器(接口是服务实现的契约);接口不能包含任何构造器的实现代码。
即使约束一个泛型接口的类型参数来源于另一个接口,也要十分谨慎地使用。例如,如果想要增加一个方法用来从List中移除一个特定item,就可能会对IList<T>增加一个IComparable<T>约束:
public interface IList<T> where T:IComparable<T>
{
void Remove(T item);
//Rest of the interface
}
当实现该方法时会常常包含对List中item的比较操作,反之就表明类型参数需要支持IComparable<T>接口,这仍旧是一个“实现细节”。或许有其他方式来实现对类型参数的比较,或许根本没有实现。但任何情况都是与纯粹的接口定义毫不相干的。让类实现带有约束的泛型接口,保持接口自身的约束自由:
public class List<T> : IList<T> where T : IComparable<T>
{
public void Remove(T item)
{...}
//Rest of the implementation
}
蓝色文字原文,请朋友们帮忙指正翻译一下:
If you want this level of strong typing with polymorphism,define a new interface dedicated to managing customers,instead of skewing the general-purpose difinition of the generic IList<T>。
接口与泛型部分仍有部分残余,下次终结它。。。
根据原版英文翻译总结的,所以不足和错误之处请大家不吝指正,谢谢:)