首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么协方差比polymorphism...and更酷而不是冗余?

为什么协方差比polymorphism...and更酷而不是冗余?
EN

Stack Overflow用户
提问于 2011-01-05 03:36:49
回答 3查看 844关注 0票数 9

.NET 4引入了协方差。我想它是有用的。毕竟,MS费尽心思才把它添加到C#语言中。但是,为什么协方差比好的旧多态性更有用呢?

我写这个例子是为了理解为什么我应该实现协方差,但我仍然不明白。请给我开导一下。

代码语言:javascript
复制
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Sample
{
    class Demo
    {
        public delegate void ContraAction<in T>(T a);

        public interface IContainer<out T>
        {
            T GetItem();
            void Do(ContraAction<T> action);
        }

        public class Container<T> : IContainer<T>
        {
            private T item;

            public Container(T item)
            {
                this.item = item;
            }

            public T GetItem()
            {
                return item;
            }

            public void Do(ContraAction<T> action)
            {
                action(item);
            }
        }

        public class Shape
        {
            public void Draw()
            {
                Console.WriteLine("Shape Drawn");
            }
        }

        public class Circle:Shape
        {
            public void DrawCircle()
            {
                Console.WriteLine("Circle Drawn");
            }
        }

        public static void Main()
        {
            Circle circle = new Circle();
            IContainer<Shape> container = new Container<Circle>(circle);
            container.Do(s => s.Draw());//calls shape

            //Old school polymorphism...how is this not the same thing?
            Shape shape = new Circle();
            shape.Draw();
        }
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-01-05 03:44:06

考虑一个请求IContainer<Shape>的API。

代码语言:javascript
复制
public void DrawShape(IContainer<Shape> container>) { /* ... */ }

你有一个Container<Circle>。如何将容器传递给DrawShape应用程序接口?如果没有协方差,则不能将类型Container<Circle>转换为IContainer<Shape>,这要求您重新包装该类型或想出一些其他解决方法。

这在使用大量泛型参数的API中并不少见。

票数 10
EN

Stack Overflow用户

发布于 2011-01-05 03:50:59

协方差比多态性更酷,就像长颈兔比冰鞋更酷一样:它们不是一回事。

协方差和逆方差(以及不变性and...omnivariance...anybody?)处理泛型在继承方面的“方向”。在您的示例中,您正在做相同的事情,但这不是一个有意义的示例。

例如,考虑IEnumerable<T>out T这一事实。这让我们可以这样做:

代码语言:javascript
复制
public void PrintToString(IEnumerable<object> things)
{
    foreach(var obj in things)
    {
        Console.WriteLine(obj.ToString());
    }
}

public static void Main()
{
    List<string> strings = new List<string>() { "one", "two", "three" };
    List<MyClass> myClasses = new List<MyClass>();

    // add elements to myClasses

    PrintToString(strings);
    PrintToString(myClasses);
}

在以前的C#版本中,这是不可能的,因为List<string>实现了IEnumerableIEnumerable<string>,而不是IEnumerable<object>。但是,由于IEnumerable<T>out T,我们知道它现在可以兼容任何IEnumerable<Y>的赋值或参数传递,其中T is YT:Y

在以前的版本中,通过使函数本身成为泛型并使用泛型类型推断,可以在某些情况下解决这类问题,在许多情况下会产生相同的语法。然而,这并没有解决更大的问题,也绝不是100%的变通方法。

票数 5
EN

Stack Overflow用户

发布于 2011-01-05 03:45:12

它是的泛型版本:

代码语言:javascript
复制
object[] arr = new string[5];

我要说的是,是否真的需要它是一个观点问题,因为它可能会引入像这样的话时发生的错误:

代码语言:javascript
复制
arr[0] = new object(); //Run-time error

但有时它会非常方便,因为它可以让你更好地重用代码。

编辑:

我忘了--如果使用得当,您可以通过使用outin关键字来防止这些bug。所以没有太多的缺点。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4597612

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档