Ответ 1
Ваш код компилируется и работает, так ли это "правильно"? Наверное, это так!
Однако не очень интересно иметь стек, который содержит только один элемент; что на самом деле не стек. Подумайте о том, как вы можете сделать действительно ковариантный и контравариантный стек.
interface IPush<in T> { void Push(T item); }
interface IPop<out T> { T Pop(); }
class Stack<T> : IPush<T>, IPop<T>
{
private class Link
{
public T Item { get; private set; }
public Link Next { get; private set; }
public Link(T item, Link next) { this.Item = item; this.Next = next; }
}
private Link head;
public Stack() { this.head = null; }
public void Push(T item)
{
this.head = new Link(item, this.head);
}
public T Pop()
{
if (this.head == null) throw new InvalidOperationException();
T value = this.head.Item;
this.head = this.head.Next;
return value;
}
}
И теперь вы можете использовать стек ковариантно для выскакивания и контравариантно для нажатия:
Stack<Mammal> mammals = new Stack<Mammal>();
IPop<Animal> animals = mammals;
IPush<Giraffe> giraffes = mammals;
IPush<Tiger> tigers = mammals;
giraffes.Push(new Giraffe());
tigers.Push(new Tiger());
System.Console.WriteLine(animals.Pop()); // Tiger
System.Console.WriteLine(animals.Pop()); // Giraffe
Что делать, если я хочу использовать только один экземпляр B из ссылки A?
Ваш вопрос: "Что, если я хочу использовать Тигра, но у меня есть ссылка на Animal?" Ответ "вы не можете", потому что животное не может быть тигром! Если вы хотите проверить, действительно ли ссылка на Animal является тигром, скажите:
Tiger tiger = myAnimal as Tiger;
if (tiger != null) ...
или
if (myAnimal is Tiger) ...
Как насчет того, хотите ли вы преобразовать класс
C<B>
вC<A>
?
Это невозможно. Здесь нет ссылки. Единственные ковариантные и контравариантные ссылочные преобразования в С# 4 относятся к общим интерфейсам и общим делегатам, которые построены с ссылочными типами как аргументы типа. Родовые классы и структуры не могут использоваться ковариантно или контравариантно. Лучшее, что вы можете сделать, это сделать класс реализованным вариантом интерфейса.