【问题标题】:How to properly implement concrete class that inherits interface with List<AnotherInterface> [duplicate]如何正确实现继承接口的具体类 List<AnotherInterface> [重复]
【发布时间】:2019-05-10 09:44:55
【问题描述】:

我有一个建议的字典项架构,如下所示:

public interface IDataDictionary
{
    List<IDataDictionaryItem> DictionaryItems { get; set; }
}

而字典项为:

public interface IDataDictionaryItem
{
    Guid Guild { get; set; }

    int SequenceId { get; set; }

    string Title { get; set; }

    string Value { get; set; }

    string Description { get; set; }

    string Language { get; set; }

} 

当我尝试在这样的具体类中实现它时:

public class HairColorDictionary : IDataDictionary
{
    public List<HairColor> DictionaryItems { get; set; }
}

项目具体实现:

public class HairColor : IDataDictionaryItem
{
    public Guid Guild { get; set; }
    public int SequenceId { get; set; }
    public string Title { get; set; }
    public string Value { get; set; }
    public string Description { get; set; }
    public string Language { get; set; }
}

我收到以下错误消息,但我似乎无法理解它。 有人可以告诉我哪里出错了。

错误信息:

错误 CS0738“HairColorDictionary”未实现接口成员“IDataDictionary.DictionaryItems”。 “HairColorDictionary.DictionaryItems”无法实现“IDataDictionary.DictionaryItems”,因为它没有匹配的返回类型“List”。

【问题讨论】:

  • 与引用的可能重复项有一定的相似性,但这无疑从不同的角度提供了对问题/解决方案的更好理解。

标签: c#


【解决方案1】:

在您的实现中,HairColorDictionary is-a IDataDictionary。所以我可以做一些不好的事情,比如:

IDataDictionary d = new HairColorDictionary();
d.DictionaryItems.add(blah);

这里的 add 方法需要 IDataDictionaryItem 类型的东西,但不一定是 HairColor,因为 d 只是 IDataDictionary 而不是 HairColorDictionary!所以我可以做类似的事情

class SkinColor : IDataDictionaryItem { ... }
IDataDictionaryItem s = new SkinColor();
d.DictionaryItems.add(s);

问题是这最后的陈述是否有效?它应该是有效的,因为 add 期望 IDataDictionaryItem 正确实现 SkinColor。但是它应该是无效的,因为实际的public List&lt;HairColor&gt; DictionaryItems 只允许HairColors 而不是SkinColors!!!

要消除所有这些混淆并保持严格的类型安全,您必须遵循协变和逆变规则。或者你可以继续使用@TheMuffinMan 的不错的answer

【讨论】:

  • 是的,同意。在问这个问题之前,我没有意识到这种可能性。当然是因为不了解。我从中学到了宝贵的一课。并感谢您也为它提供了一些精简版!
【解决方案2】:

我了解您想要了解的内容以及它不起作用的原因是因为接口定义了一个非特定的集合(可以实现该接口),但您正在尝试实现该接口成员以特定的方式。

如果你真的必须这样做,你可以使用泛型来做到这一点。这是更新的位:

public interface IDataDictionary<T> where T : IDataDictionaryItem
{
    List<T> DictionaryItems { get; set; }
}

public class HairColorDictionary : IDataDictionary<HairColor>
{
    public List<HairColor> DictionaryItems { get; set; }
}

T 允许您使用任何东西,where T:... 部分对其进行了限制。

请意识到这是您解决方案的潜在答案。我没有花时间去思考它的优点或缺点。

【讨论】:

  • 这实际上解决了我的问题,也让我更好地理解了接口继承的工作原理。谢谢!
猜你喜欢
  • 2018-04-05
  • 1970-01-01
  • 2011-11-21
  • 2010-09-27
  • 2022-01-23
  • 1970-01-01
  • 2019-01-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多