Рассмотрим эту глупую программу, которая ничего не делает:
interface I<out T> { }
class A1 : I<A1> { }
class A2 : A1, I<A2> { }
class B1 { }
class B2 : B1, I<B2> { }
class C1 : I<A1> { }
class C2 : C1, I<A2> { }
static class Program
{
static void f<T>(I<T> obj)
{
}
static void Main()
{
f<A1>(new A2());
f<A2>(new A2());
f<B1>(new B2());
f<B2>(new B2());
f<A1>(new C2());
f<A2>(new C2());
}
}
Это показывает, что A2
и C2
реализуют как I<A1>
, так и I<A2>
, а B2
реализует как I<B1>
, так и I<B2>
.
Однако, изменив это на
static void Main()
{
f(new A2());
f(new B2());
f(new C2());
}
показывает, что в первой и третьей строках аргумент f
generic type не может быть выведен из переданного аргумента, но во второй строке это может быть.
Я понимаю, что здесь делает компилятор, поэтому не нужно объяснять. Но как я могу обойти это? Есть ли способ изменить это, чтобы я мог определить интерфейс как для базового, так и для производного класса, но при работе с производным классом у вас есть операция вывода типа?
Что я имел в виду, так это искать способ "скрыть" интерфейсы, основанные на базовом классе, чтобы компилятор их не видел и не использовал, даже если они существуют. Однако С#, похоже, не дает возможности сделать это.
Уточнение: в моей глупой примерной программе A1
реализует I
сам по себе как аргумент общего типа. У меня есть это в моем реальном коде, но у меня также есть классы, которые реализуют I
с другим общим аргументом типа и добавили C1
и C2
к моему примеру кода по этой причине.