Рассмотрим эту реализацию:
public class MyClass<T1, T2> : IMyInterface<T1, T2>, IMyInterface<T2, T1>
{
/* implementation for IMyInterface<T1, T2> here. */
/* implementation for IMyInterface<T2, T1> here. */
}
Что MyClass<int, int>
реализует? Он реализует IMyInterface<int, int>
дважды, потому что IMyInterface<T1, T2>
и IMyInterface<T2, T1>
объединяются, когда T1
и T2
равны. Вот почему реализация 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>
{
/* implementation for IMyInterface<T1, T2> here. */
}
public class MyClassBase<T1, T2> : IMyInterface<T2, T1>
{
/* implementation for IMyInterface<T2, T1> here. */
}
Что вы сделали, так это поставили 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)
. Если бы вы явно реализовали I<T2, T1>
на B<T1, T2>
(добавив к имени метода префикса 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)
{
//Outputs "A: M(0, 1)"
var a = new A<int, int>();
a.M(0, 1);
//Outputs "B: M(0, 1)"
var b = new B<int, int>();
b.M(0, 1);
//Outputs "A: M(0, 1)" because I<T1, T2>
//takes precedence over I<T2, T1>
var a_as_i = a as I<int, int>;
a_as_i.M(0, 1);
//Outputs "B: M(0, 1)" despite being called on an instance of A
var a_as_b = a as B<int, int>;
a_as_b.M(0, 1);
Console.ReadLine();
}
}
person
Timothy Shields
schedule
28.03.2014