假设
甲级 { }
B 类:A {}
泛型类不支持协变。
意思——我们不能做这样的事情:
MyConverter<B> x1= new MyConverter<B>();
MyConverter<A> x2= x1;
很好理解。
根据我的阅读 - 我知道协方差将可用:
“如果您使用在泛型类上实现的后备泛型接口(interface) - 则可以通过这些接口(interface)访问 T 类型对象实例”。
我只有一个问题。
我见过很多“转换器”类作为 Stack
形式的例子。
但从来不明白“如果我只想使用 A 的引用中的 1 个 B 实例怎么办?”
所以我尝试了一些代码:
Create
B
object + values ---> use Generic Converter forB
---> use the covariance flow to get itsA
reference ---> now you can use it either as A or as B.
我的问题:
这是执行此操作的正确方法吗(仅对 1 个对象使用协方差)?
附注 该代码正在运行并且编译正常。 http://i.stack.imgur.com/PJ6QO.png
最近我一直在询问/阅读很多关于这个主题的内容 - 我深入研究事物是为了尽我所能地理解它们。
最佳答案
您的代码可以编译并运行,那么它“正确”吗?我想是的!
然而,只包含一个元素的堆栈并不是很有趣;那不是真正的堆栈。让我们考虑一下如何制作真正协变和逆变的堆栈。
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
What if I want to use only one instance of B from a reference of A?
您的问题是“如果我想使用 Tiger 但我有一个 Animal 引用怎么办?”答案是“你不能”,因为动物可能不是老虎!如果你想测试对 Animal 的引用是否真的是一只老虎,那么说:
Tiger tiger = myAnimal as Tiger;
if (tiger != null) ...
或
if (myAnimal is Tiger) ...
What about if you want to convert class
C<B>
toC<A>
?
那是不可能的。那里没有引用转换。 C# 4 中唯一的协变和逆变引用转换在泛型接口(interface) 和泛型委托(delegate) 上,它们以引用类型作为类型参数构造。 泛型不能协变或逆变地使用类和结构。您能做的最好的事情就是让类实现一个变体接口(interface)。
关于C#协变结构理解?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9229491/