【问题标题】:Is it Covariance and Contravariance related issue?是协方差和逆变相关的问题吗?
【发布时间】:2012-09-13 23:17:28
【问题描述】:

我有以下代码:

class Header<TItem> where TItem : IItem { IEnumerable<TItem> Item { get; set; } }
class HeaderA : Header<ItemA> { public HeaderA(int a) {...} } 
class HeaderB : Header<ItemB> { public HeaderB(int b) {...} } 

interface IItem {...}
class ItemA : IItem { }
class ItemB : IItem { }

public static List<Header<IItem>> list = new List<Header<IItem>> 
{
    new HeaderA(1)
}

最后一个new HeaderA(1)的编译错误是

Error   1   The best overloaded Add method
'System.Collections.Generic.List<NS.Header<NS.IItem>>.Add(NS.Header<NS.IItem>)'
for the collection initializer has some invalid arguments

如何解决这个问题?

【问题讨论】:

  • new ItemA() 看起来不像被调用了。你的意思是new HeaderA(1)
  • @Brad 谢谢。我已经更正了。

标签: c# generics covariance contravariance


【解决方案1】:

您正在尝试将Header&lt;ItemA&gt; 添加到List&lt;Header&lt;IItem&gt;&gt;。这需要从Header&lt;ItemA&gt;Header&lt;IItem&gt; 的转换——而且这种转换不存在。它不存在是有充分理由的。想象一下您的代码是有效的......那么这将起作用:

List<Header<IItem>> list = ...; // As per code
Header<IItem> header = list[0];
header.Item = new List<IItem>();

现在请记住 header 实际上HeaderA - 所以这个工作相当于这个 标头A标头=新标头A(); header.Item = new List { new ItemB() };

如果其他人认为 header.ItemIEnumerable&lt;ItemA&gt;();,那就不好了 - 所以 这个 应该没问题:

ItemA itemA = header.Item.First();

...如果您在其中添加了ItemB,显然不会。

基本上,您正在寻找泛型协方差 - 但您只能在接口和委托上声明它(而不是在 Header&lt;TItem&gt; 等类上),并且只有当类型参数 不是由于Item setter,在输入位置使用。

也许更重要的是,您的设计看起来非常复杂 - 我强烈怀疑如果您退后一步,您可以设计自己的方式来尝试这样做。

【讨论】:

  • 谢谢,你能详细说明“退一步”吗?
  • @NickW:嗯,我们不知道这里的大局——为什么你有这些类型。看看您是否可以在不需要协方差的情况下实现相同的更大目标。
  • 原来我只有 Header 和 Item。后来我发现还有其他类和 HeaderA 和 ItemA 类似,只是差别很小。所以 Header 和 Item 变成 HeaderA, HeaderB, ... 和 ItemA, ItemB, ....
  • @NickW:说实话,这还不足以提供帮助。我认为您可能必须尝试自己解决这个问题。
  • 其实这个设计是关于另一个问题的。 stackoverflow.com/questions/12410890/type-constraint
猜你喜欢
  • 2014-09-01
  • 2011-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多