.NET 4引入了协方差。我想它是有用的。毕竟,MS费尽心思才把它添加到C#语言中。但是,为什么协方差比好的旧多态性更有用呢?
我写这个例子是为了理解为什么我应该实现协方差,但我仍然不明白。请给我开导一下。
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();
}
}
}发布于 2011-01-05 03:44:06
考虑一个请求IContainer<Shape>的API。
public void DrawShape(IContainer<Shape> container>) { /* ... */ }你有一个Container<Circle>。如何将容器传递给DrawShape应用程序接口?如果没有协方差,则不能将类型Container<Circle>转换为IContainer<Shape>,这要求您重新包装该类型或想出一些其他解决方法。
这在使用大量泛型参数的API中并不少见。
发布于 2011-01-05 03:50:59
协方差比多态性更酷,就像长颈兔比冰鞋更酷一样:它们不是一回事。
协方差和逆方差(以及不变性and...omnivariance...anybody?)处理泛型在继承方面的“方向”。在您的示例中,您正在做相同的事情,但这不是一个有意义的示例。
例如,考虑IEnumerable<T>是out T这一事实。这让我们可以这样做:
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>实现了IEnumerable和IEnumerable<string>,而不是IEnumerable<object>。但是,由于IEnumerable<T>是out T,我们知道它现在可以兼容任何IEnumerable<Y>的赋值或参数传递,其中T is Y或T:Y。
在以前的版本中,通过使函数本身成为泛型并使用泛型类型推断,可以在某些情况下解决这类问题,在许多情况下会产生相同的语法。然而,这并没有解决更大的问题,也绝不是100%的变通方法。
发布于 2011-01-05 03:45:12
它是的泛型版本:
object[] arr = new string[5];我要说的是,是否真的需要它是一个观点问题,因为它可能会引入像这样的话时发生的错误:
arr[0] = new object(); //Run-time error但有时它会非常方便,因为它可以让你更好地重用代码。
编辑:
我忘了--如果使用得当,您可以通过使用out和in关键字来防止这些bug。所以没有太多的缺点。
https://stackoverflow.com/questions/4597612
复制相似问题