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

本文关键字:方差第 2部 泛型 继承 | 更新日期: 2023-09-27 17:51:12

这是我的原始线程: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;

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

这个问题似乎没有什么问题,所以我将编几个问题来回答。

什么是协变转换?

假设有几种类型FruitAppleBanana,它们之间的关系很明显;AppleFruit的一种,等等。

协变转换是指类型实参的可转换性意味着泛型类型的可转换性。若Apple可转换为Fruit, Bowl<Apple>可转换为Bowl<Fruit>,则Bowl<T>在t中是协变的。

什么是逆变变换?

逆变转换是协变转换,它使反转的方向而不是保持的方向。如果Eater<Fruit>可转换为Eater<Apple>,则Eater<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(); });

遵循逻辑。这个程序将一个苹果作为Banana.Peel()的" This "传递,这显然是错误的。

编译器知道这种情况可能发生,因此一开始就不允许声明接口。


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

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

http://blogs.msdn.com/b/ericlippert/archive/tags/covariance +和+抗变性/

如果你仍然有问题,那么你应该在这里发布包含问题的问题,而不是让人们猜测问题的真正内容。