在c#中,接口引用另一个接口,而类引用另一个类

本文关键字:另一个 引用 接口 | 更新日期: 2023-09-27 18:11:53

我有一个很简单的问题,但是我以前从来没有遇到过这个问题。

看一下这段代码:

interface IFoo
{
    IBar MyBar { get; }
}
interface IBar
{
    String Test { get; }
}
class Foo : IFoo
{
    public Bar MyBar { get; set; }
}
class Bar : IBar
{
    public String Test { get; set; }
}

问题是Foo没有实现IFoo,因为它返回Bar而不是IBar。但我不觉得有什么问题,因为Bar正在实现IBar。我错过什么了吗?

我希望我的应用程序使用类Foo,但将IFoo暴露给解决方案的其他部分。

这是一种绕过它的方法,但它似乎是一个丑陋的解决方案:

class Foo : IFoo
{
    public Bar MyBar { get; set; }
    IBar IFoo.MyBar { 
        get { return this.MyBar; }
    }
}

这是正确的方法,还是更好的方法?

在c#中,接口引用另一个接口,而类引用另一个类

你可以这样做:

interface IFoo<out B> where B:IBar
{
    B MyBar { get; }
}
interface IBar
{
    String Test { get; }
}
class Foo : IFoo<Bar>
{
    public Bar MyBar { get; set; }
}
class Bar : IBar
{
    public String Test { get; set; }
}

这只在B处于输出位置的情况下才有效(原因很明显,如果您考虑的时间足够长)。

问题是Foo没有实现IFoo,因为它返回Bar而不是IBar。但我不觉得有什么问题,因为Bar正在实现IBar。我错过什么了吗?

是的。你误解了IFoo接口的契约。合同很简单:

一个名为MyBar的属性,它有一个getter, 有一个返回类型IBar。约定不是它返回一个IBar类型的对象,而是返回类型为IBar。

这是标准的。尝试实现ICloneable接口,它只有一个方法Clone(),返回类型为object。实现这个接口意味着无论如何必须实现一个返回类型为object的方法。即使您想更具体一点,任何其他返回类型都不符合条件。

你建议的绕过它的方法是正确的方法之一——使用一个返回Bar属性的IBar属性。或者,你可以有一个IBar属性并设置它为一个Bar实例,因为那是完全有效的,然后通过IBar契约与你的IBar对象一起工作。这将有助于脱钩。