Понимание контравариантности в C#
Я учусь на контравариантности и попробовал следующее, чтобы впитать концепцию:
interface B<T>
{
T h();
}
public class SomeOtherClass<T> : B<T>
{
public T h()
{
return default(T);
}
}
public class Trial
{
static void Main()
{
SomeOtherClass<Derived> h = new SomeOtherClass<Derived>();
Base b = h.h();
}
}
Я ожидал, что этот код выдаст ошибку при последнем утверждении, и подумал, что создание T-контравариантного исправит это. Тем не менее, это работает как есть. Заставляет меня задуматься, где контравариантность находит применение?
2 ответа
Решение
Generics Varriance используется в интерфейсе и Delgates
Измените свой код на ниже, и вы получите ошибку
public class Trial
{
static void Main()
{
B<Derived> h = new SomeOtherClass<Derived>();
B<Base> b = h; // you will get compilation error until you add out keyword in interface B
}
}
Ключевое слово Here out (Contravariant) - это способ сказать компилятору, что экземпляр B безопасен, чтобы считаться b
using System;
using static System.Console;
////
namespace ConsoleApplication1
{
interface iContravariance<in T>
{
void Info(T t);
}
class Master<T> : iContravariance<T>
{
public void Info(T insT)
{
if (insT is Parent) {
WriteLine("--- As Parent: ---");
WriteLine((insT as Parent).Method());
}
if (insT is Child) {
WriteLine("--- As Child: ---") ;
WriteLine((insT as Child).Method());
}
}
}
class Parent {
public virtual String Method()
{
WriteLine("Parent Method()");
return "";
}
}
class Child : Parent {
public override String Method()
{
WriteLine("Child Method()");
return "";
}
}
class Client
{
static void Main(string[] args)
{
Child child = new Child();
Parent parent = new Parent();
iContravariance<Parent> interP = new Master<Parent>();
iContravariance<Child> interC = interP;
interC.Info(child);
//interC.Info(parent); (It is compilation error.)
ReadKey();
return;
}
}
}
Выход:
--- As Parent: ---
Child Method()
--- As Child: ---
Child Method()