考虑这个实现:
Consider this implementation:
public class MyClass<T1, T2> : IMyInterface<T1, T2>, IMyInterface<T2, T1>
{
}
MyClass<int, int>
实现了什么?它实现了IMyInterface<int, int>
两次,因为当T1
和T2
相等时,IMyInterface<T1, T2>
和IMyInterface<T2, T1>
会合并。这就是为什么在同一个类上同时实现IMyInterface<T1, T2>
和IMyInterface<T2, T1>
是不允许的。如果你尝试实现例如IMyInterface<int, T1>
和IMyInterface<T2, double>
,同样的推理会适用:类型表达式会对于T1=double, T2=int
进行统一。
考虑下面的实现:
public class MyClass<T1, T2> : MyClassBase<T1, T2>, IMyInterface<T1, T2>
{
}
public class MyClassBase<T1, T2> : IMyInterface<T2, T1>
{
}
你所做的是将优先级放在
IMyInterface<T1, T2>
上,而不是
IMyInterface<T2, T1>
。如果
T1
和
T2
相等,并且你有一个
MyClass<T1, T2>
实例,则会选择
IMyInterface<T1, T2>
实现。如果你有一个
MyBaseClass<T1, T2>
实例,则会选择
IMyInterface<T2, T1>
实现。
以下是一个示例程序,展示了这些行为。特别注意
a_as_i.M(0, 1)
和
a_as_b.M(0, 1)
的行为。如果你要在
B<T1, T2>
上显式实现
I<T2, T1>
(通过在方法名前加上
I<T2, T1>.
),则无法使用编译时语法调用它。需要使用反射。
interface I<T1, T2>
{
void M(T1 x, T2 y);
}
class A<T1, T2> : B<T1, T2>, I<T1, T2>
{
public void M(T1 x, T2 y)
{
Console.WriteLine("A: M({0}, {1})", x, y);
}
}
class B<T1, T2> : I<T2, T1>
{
public void M(T2 x, T1 y)
{
Console.WriteLine("B: M({0}, {1})", x, y);
}
}
class Program
{
static void Main(string[] args)
{
var a = new A<int, int>();
a.M(0, 1);
var b = new B<int, int>();
b.M(0, 1);
var a_as_i = a as I<int, int>;
a_as_i.M(0, 1);
var a_as_b = a as B<int, int>;
a_as_b.M(0, 1);
Console.ReadLine();
}
}