C# 接口继承

C# 接口继承,c#,interface,C#,Interface,如果我有一个接口: interface IFoo { int Offset {get;} } 我可以要这个吗 interface IBar: IFoo { int Offset {set;} } 所以IBar的消费者将能够设置或获取?这很接近,但没有香蕉 interface IFoo { int Offset { get; } } interface IBar : IFoo { new int Offset { set; } } class Thin

如果我有一个接口:

interface IFoo
{
    int Offset {get;}
}
我可以要这个吗

interface IBar: IFoo
{   
    int Offset {set;}
}

所以IBar的消费者将能够设置或获取?

这很接近,但没有香蕉

interface IFoo
{
    int Offset { get; }
}

interface IBar : IFoo
{
    new int Offset { set; }
}

class Thing : IBar
{
    public int Offset { get; set; }
}
注意IBar中的
new
关键字,但这会覆盖IFoo的get访问器,因此IBar没有get。因此,不,您实际上不能创建只添加一个集合而保留现有get的IBar。

不,您不能

(我正要写“是”,但在读了安东尼的帖子,并尝试了一些调整后,我发现答案是否定的!)

(正如Anthony指出的,将生成一个警告,可以通过添加“new”关键字来修复。)

尝试代码时:

IBar a = new FooBar();
a.Offset = 2;
int b = a.Offset;
最后一行将生成编译错误,因为您隐藏了IBar的偏移量设置器

编辑:修复了类中属性的ACCESIBILITY修饰符。安东尼

+1至Arjan Einbu

当然,IBar的使用者将无法获得Offset属性的值,因为IFoo的继承不会改变在IBar中定义的Offset属性的语义——编译器警告您是有原因的。当您使用“new”关键字时,编译器会完全消除歧义,并将IBar.Offset视为只写。然而,从IBar接口继承的类的使用者将能够获取和设置偏移量属性

如果使用显式接口实现,则差异会变得更加明显:

class Boo: IBar
{
    int IFoo.Offset { get { return 0; } }
    int IBar.Offset 
    {
          set { }  // OK - IBar has a setter
          get { return 1; } // compiler error - IBar.Offset doesn't inherit setter

    }
}

class Program
{
    static void Main(string[] args)
    {
        Boo b = new Boo();
        int x = ((IFoo) b).Offset; // OK - IFoo.Offset has getter
        ((IBar) b).Offset = 1; // OK - IBar.Offset has setter
        x = ((IBar) b).Offset; // compiler error - IBar doesn't inherit 
                               // getter from IFoo
    }
}

您可以做的是让IBar接口具有getter和setter(没有这一点是没有意义的)。当您在IBar中只有setter时,您实际上明确地说“在IBar接口上,Offset属性是write only”,这显然不是您想要的

interface IFoo 
{ 
    int Offset { get;}
}

interface IBar : IFoo 
{
    new int Offset { get; set; } 
}

class Thing : IBar 
{
    public int Offset
    {
        get;
        set;
    }
}
现在您可以像这样使用类:

var t = new Thing();
t.Offset = 1;
int read = t.Offset;

如果属性getter和setter是独立的实体,那么定义属性setter并从定义属性getter的接口继承的接口将允许读写语义。不幸的是,不管出于什么原因,vb.net和C#都不允许这样做。相反,getter是只读属性,setter是只读属性。如果某个类型定义了一个只读属性,但继承了一个只读属性,则vb.net和C#将只看到该只读属性。如果接口继承了一个公开只读属性的接口和一个公开只读属性的接口,那么这两个属性在接口上都不可用,因为vb.net和C#都不愿意使用正在读或写属性的事实来确定是使用只读属性还是只写属性。相反,两种语言都将声明该属性“不明确”


如前所述,解决方案是拥有一个接口,该接口继承一个具有只读属性的接口,并实现一个读写属性。这将隐藏另一个只读属性,但如果实现读写属性以返回相同的数据,这应该不会是问题。事实上,C#中处理隐式接口实现的方式允许使用相同的代码实现读写和只读接口(vb会要求将“只读”属性与“读写”属性分开编码,这有点麻烦)。

Anthony您测试了从IBar继承的类,但问题是关于IBar接口的使用者您的代码是编译的,但使用IBar接口调用东西的setter不会编译。请注意,在我的回答中,Offset属性在类中是公共的。使用隐式实现是一个很好的示例!帕特里克,你没有抓住要点——IBar的消费者将无法获得价值。隐式实现IBar的类的使用者将能够获取/设置。在显式实现的情况下,您将无法直接访问偏移量属性。正如Anthony的示例一样:您的代码可以编译,但使用IBar接口调用东西的setter仍然无法编译。您完全正确,我没有抓住要点,我读错了。它可以工作,因为您正在更改接口。现在你把伊福的塞特藏起来了。现在可以使用隐式iterface实现两个不同的setter。是的,我指出了这一点。IBar上的Offset属性有一个getter和一个setter,没有理由只在想要的行为是设置和获取时才写入bar。我在下面编辑了我的答案,真正的问题是为什么IBar-interface中没有getter。在这里了解接口的概念
var t = new Thing();
t.Offset = 1;
int read = t.Offset;