C# имеет ограниченную поддержку этой функции с помощью дженериков и универсального модификатора out
. (См.: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/out-generic-modifier)
Поддержка ограничена, поскольку работает только с интерфейсами. Чтобы переписать принятый ответ:
public class Base1
{
}
public class Derived1 : Base1
{
}
public interface Base2<out T> where T : Base1
{
T Method();
}
public class Derived2 : Base2<Derived1>
{
public Derived1 Method()
{
return new Derived1();
}
}
В этом случае Derived2
будет реализовывать не только Base2<Derived1>
, но и Base2<Base1>
.
Принцип вступает в силу, потому что если вы вызовете Method
через интерфейс Base2<Base1>
, он будет иметь тип возврата Base1
, но если вы вызовете его через Derived2
, он будет иметь тип возврата Derived1
.
Точно так же вы можете реализовать контравариантность параметров с помощью универсального модификатора in
: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/in-generic-modifier
Обратите внимание, что нарушать принцип невозможно. Если в приведенном выше примере вы измените ключевое слово out
на ключевое слово in
, исходный код не будет скомпилирован, и вы получите следующую ошибку:
Error CS1961 Invalid variance: The type parameter 'T' must be covariantly valid on 'Base2<T>.Method()'. 'T' is contravariant.
person
Gábor Angyal
schedule
10.12.2017