-6

这是我的原始线程: C# 泛型继承和协变

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

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;
4

1 回答 1

8

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

什么是协变转换?

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

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


什么是逆变转换?

逆变转换是反转方向而不是保留方向的协变转换。IfEater<Fruit>可转换为Eater<Apple>thenEater<T>在 T 中是逆变的。


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

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

这是为了助记:协变接口通常具有类型参数出现在输出位置,而逆变接口通常具有类型参数出现在输入位置。


String可转换为Object。我怎样才能使IReadOnlyCollection<String>转换为IReadOnlyCollection<Object>

IReadOnlyCollection<T>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(); });

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

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


如果我有更多关于方差的问题,我该怎么办?

您应该首先阅读我关于该功能的设计和实现的文章。从底部开始;它们按时间倒序排列:

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

如果您仍有问题,那么您应该在此处发布实际包含问题的问题,而不是让人们猜测问题的真正含义。

于 2013-01-10T18:07:08.820 回答