【问题标题】:C# generic inheritance and covariance part 2C# 泛型继承和协变第 2 部分
【发布时间】:2013-01-10 17:39:38
【问题描述】:

这是我的原帖: 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;

【问题讨论】:

  • 顺便说一句,ItemType 应该被称为T
  • 与其让CopyToArray 返回Array,不如让它返回ItemType[],这样它就被强类型化了。
  • 这个问题似乎没有任何问题。 “我希望继承起作用”不是问题。如果您想要答案,请将其重写为问题。编译器是正确的;此代码不是类型安全的。
  • 服务会很好,但是接口上的继承不起作用。能够做到这一点也很好。我编辑了这个问题,以便更清楚我想要做什么。
  • @RyanBrown:这个问题被否决了,因为它是一个问得不好的问题。非常不清楚您要问什么,因为其中没有实际问题,几乎没有证据表明您进行过任何研究,并且您接受的回答率极低。如果你真的想让每个人的事情都变得更好,那就做你的研究,提出明确的问题,并接受好的答案。

标签: c# generics


【解决方案1】:

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

什么是协变转换?

假设我们有一些类型 FruitAppleBanana 具有明显的关系; AppleFruit 的一种,以此类推。

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


什么是逆变转换?

逆变转换是一种协变转换,它反转方向而不是保留它。如果Eater&lt;Fruit&gt; 可转换为Eater&lt;Apple&gt;,则Eater&lt;T&gt; 在T 中是逆变的。


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

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

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


String 可转换为Object。如何将IReadOnlyCollection&lt;String&gt; 转换为IReadOnlyCollection&lt;Object&gt;

在 T 中使 IReadOnlyCollection&lt;T&gt; 协变。标记为 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/

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

【讨论】:

  • 你说得对,我真的很想退出,现在只是告诉编译器 ContainsItem 不关心类型,只要它是引用类型...
  • @RyanBrown 见我上面的评论。要告诉编译器您“不关心”ContainsItem 方法的参数类型,请将其设为继承自 ItemType 的新泛型类型,如下所示:bool ContainsItem&lt;T&gt;(T item) where T : ItemType;
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多