C#协变结构理解?

标签 c# .net-4.0 covariance

  • 假设

    甲级 { }

    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 for B ---> use the covariance flow to get its A reference ---> now you can use it either as A or as B.

enter image description here

enter image description here

我的问题:

这是执行此操作的正确方法吗(仅对 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> to C<A>?

那是不可能的。那里没有引用转换。 C# 4 中唯一的协变和逆变引用转换在泛型接口(interface) 和泛型委托(delegate) 上,它们以引用类型作为类型参数构造。 泛型不能协变或逆变地使用类和结构。您能做的最好的事情就是让类实现一个变体接口(interface)

关于C#协变结构理解?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9229491/

相关文章:

c# - (407) 需要代理身份验证

c# - 如何在 MigraDoc 中的表格周围添加边框?

.net - 为什么.net 4.0和.net 2.0 CLR可以存在于同一台机器上

c# - 为什么 ReadOnlyCollection 不允许协方差?

C++ 模板、多态性和模板协变

c# - 从日期范围中删除周末

c# - 如何调试通过协议(protocol)关联启动的Windows Phone 8.1 应用程序?

asp.net - <httpRuntime requestValidationMode ="2.0"/>不起作用(使用IIS 6.0)

c# - 由于 1 个编译器警告,MSBuild 4 无法构建 VS2008 csproj

matlab - 椭圆的协方差矩阵