【问题标题】:Why do i need to implement a more general interface if I already implemented a specialized one? [duplicate]如果我已经实现了一个专门的接口,为什么还需要实现一个更通用的接口? [复制]
【发布时间】:2018-02-15 06:48:54
【问题描述】:

我有一些用于域和元素的接口和类:

interface IElement {}
class FloatElement : IElement {}

interface IDomain<T> where T: IElement {}
class FloatDomain : IDomain<FloatElement>
{
    public static readonly FloatDomain Instance = new FloatDomain();
}

这是我写的

IDomain<IElement> foo = FloatDomain.Instance;

但出现错误:

(CS0266) “无法隐式转换类型 [...]。显式转换 存在(您是否缺少演员表?)”

(请注意,尽管提示“存在显式转换”,FloatDomain.Instance as IDomain&lt;IElement&gt; 将返回 null。)

我已经发现我可以通过使FloatDomain 也实现IDomain&lt;IElement&gt; 来解决这个问题。 但我想知道为什么需要这种解决方法!

在我的理解中,FloatElementIElement 的更专业版本,即我可以将FloatElement 隐式转换为IElement。正因为如此,IDomain&lt;FloatElement&gt;IDomain&lt;IElement&gt; 的更专业版本,也就是说,我还应该能够将IDomain&lt;FloatElement&gt; 隐式转换为IDomain&lt;IElement&gt;

或者换句话说:在我的理解中,IDomain&lt;IElement&gt; 就像所有其他IDomain&lt;T&gt; 的基类,其中T 实现IElement,因为T=IElement 是最普遍的可能情况。

你能指出我的推理错误吗?

【问题讨论】:

  • 了解协方差。
  • 看看List&lt;T&gt;。考虑将List&lt;string&gt; 转换为List&lt;object&gt;。然后想象当DefinitelyNotAStringAdd 编入该列表时会发生什么。

标签: c# interface hierarchy


【解决方案1】:

您尝试做的事情称为方差。在 C# 中,接口默认情况下没有变体,这就是您遇到编译错误的原因。您可以将您的界面显式标记为协变逆变以使其工作:

interface IDomain<in T> where T: IElement {}

interface IDomain<out T> where T: IElement {}

更多详情请见Variance in Generic Types

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-10
    • 1970-01-01
    • 2014-09-16
    • 2011-04-24
    • 1970-01-01
    • 2012-07-07
    • 1970-01-01
    • 2015-01-15
    相关资源
    最近更新 更多