C#协方差结构理解?

Roy*_*mir 15 c# .net-4.0 covariance

  • 假设

    A级{}

    B级:A {}

泛型类不支持协方差.

含义 - 我们不能做这样的事情:

MyConverter<B> x1= new MyConverter<B>();
MyConverter<A> x2= x1;  
Run Code Online (Sandbox Code Playgroud)

多数民众赞成并理解.

从我的阅读 - 我明白Covariance将可用:

"如果你使用支持通用接口在通用类上实现 - 那么通过这些接口可以访问T类型对象实例".

我只有一个问题.

我见过许多"转换器"类的例子Stack.

但是从来没有理解"如果我只想从A的引用中使用一个B实例怎么办?"

所以我尝试了一些代码:

创建B对象+值--->使用Generic Converter for B--->使用协方差流来获取它的A参考--->现在你可以将它用作A或B.

在此输入图像描述

在此输入图像描述

我的问题 :

这是正确的方法吗(仅对1个对象使用协方差)?

ps代码正常工作并编译好.http://i.stack.imgur.com/PJ6QO.png

我最近一直在询问/阅读很多关于这个话题的内容 - 我深入研究了一些事情,以便尽我所能地理解它们.

Eri*_*ert 16

你的代码编译和工作,它是"正确的"吗?我想是的!

但是,堆栈只包含一个元素并不是很有趣; 这不是真的堆栈.让我们考虑如何制作一个真正的协变和逆变堆栈.

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你可以使用堆栈协变弹出,并且反之则推动:

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
Run Code Online (Sandbox Code Playgroud)

如果我只想从A的引用中使用B的一个实例怎么办?

你的问题是"如果我想使用老虎但我有参考动物怎么办?" 答案是"你不能",因为动物可能不是老虎!如果你想测试对Animal的引用是否真的是老虎,那就说:

Tiger tiger = myAnimal as Tiger;
if (tiger != null) ...
Run Code Online (Sandbox Code Playgroud)

要么

if (myAnimal is Tiger) ...
Run Code Online (Sandbox Code Playgroud)

怎么样,如果你想要类转换C<B>C<A>

那是不可能的.那里没有参考转换.C#4中唯一的协变和逆变引用转换是在通用接口和通用委托上,这些委托使用引用类型作为类型参数构造.通用类和结构可能不会被共同使用或相反使用.您可以做的最好的事情是让类实现变体接口.

  • @RoyiNamir:您的愿望很容易实现.仔细研究语言及其编译器的设计和实现,每天8小时,每周5天,每年48周,5到10年,您也可以对所选择的任何编程语言有相当的了解.这就是全部. (4认同)