C#泛型继承和协方差第2部分

时间:2013-01-10 17:39:39

标签: c# generics

这是我原来的主题: C# generic inheritance and covariance

仅在我的只读接口上,我希望继承工作。

public delegate Boolean EnumerateItemsDelegate<out ItemType>(ItemType item);

public interface IReadOnlyCollection<out ItemType>
{
    Boolean ContainsItem(ItemType item);
    Array CopyToArray();
    void EnumerateItems(EnumerateItemsDelegate<ItemType> enumerateDelegate);

    UInt32 Count { get; }
    UInt32 Capacity { get; }
}

除此之外,它编译:-p

这就是我想要的工作:

IReadOnlyCollection<String> s;
IReadOnlyCollection<Object> o = s;

1 个答案:

答案 0 :(得分:5)

这个问题似乎没有任何问题,所以我会回答几个问题。

  

什么是协变转换?

我们假设我们有一些类型FruitApple以及Banana具有明显的关系; Apple是一种Fruit,依此类推。

协变转换是类型参数的可转换性意味着泛型类型的可转换性的转换。如果Apple可转换为Fruit,而Bowl<Apple>可转换为Bowl<Fruit>,则Bowl<T>在T中是协变的。


  

什么是逆变换?

逆变换是一种协变转换,反转方向而不是保留它。如果Eater<Fruit>可转换为Eater<Apple>,那么Eater<T>在T中是逆变的。


  

如何将接口或委托标记为其类型参数中的协变或逆变?

协变类型参数标记为out,逆变类型参数标记为in

这是助记符:协变接口通常在输出位置显示类型参数,而逆变接口通常在输入位置显示类型参数。


  

String可转换为Object。如何将IReadOnlyCollection<String>转换为IReadOnlyCollection<Object>

在T.中设置IReadOnlyCollection<T>协变。标记为out


  

请考虑以下代码:

delegate void Action<in T>(T t);
interface IFoo<in X>
{
  void M(Action<X> action);
}
  

为什么编译器说这是无效的?

因为它无效。让我们看看为什么。

class Foo : IFoo<Fruit>
{
  public void M(Action<Fruit> action)
  {
     action(new Apple()); // An apple is a fruit.
  }
}
...
IFoo<Fruit> iff = new Foo();
IFoo<Banana> ifb = iff; // Contravariant!
ifb.M(banana => { banana.Peel(); });

遵循逻辑。该程序将苹果作为Banana.Peel()的“this”传递,这显然是错误的。

编译器知道这可能发生,因此不允许首先声明接口。


  

如果我对方差有更多疑问,该怎么办?

您应该首先阅读有关该功能的设计和实现的文章。从底部开始;它们以反向时间顺序列出:

http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/

如果你还有问题,那么你应该在这里发布实际上包含问题的问题,而不是让人们猜出问题究竟是什么。