为什么实现具有相同属性的多个接口会显示"模糊"警告?

Man*_*ani 5 c# compiler-errors interface

相关文章:C#接口方法模糊

来自同一来源的代码:

    private interface IBase1
    {
        int Percentage { get; set; }
    }

    private interface IBase2
    {
        int Percentage { get; set; }
    }

    private interface IAllYourBase : IBase1, IBase2
    {
    }

    private class AllYourBase : IAllYourBase
    {
        private int _percentage;

        public int Percentage
        {
            get { return _percentage; }
            set { _percentage = value; }
        }
    }

    private void Foo()
    {
        IAllYourBase iayb = new AllYourBase();
        int percentage = iayb.Percentage; // Fails to compile. Ambiguity between 'Percentage' property. 
    } 
Run Code Online (Sandbox Code Playgroud)

(但不回答我的问题 - "为什么合同变得含糊不清?")

鉴于:

接口是实现类必须遵守的合同.

如果两个(或更多)接口请求相同的合同,并且接口将它们传递给"forward",然后类实现它们和ACCEPTS,那么普通合同应该只用作实现类的一个合同(通过不提供显式实现) ).然后,

  1. 为什么编译器会对共同合同显示"歧义"警告?

  2. 为什么编译器在尝试通过接口(iayb.Percentage)访问模糊合同时无法编译?

我想知道编译器使用此限制有什么好处?

编辑:提供一个真实世界的用例,我希望跨接口使用合同作为一个合同.

public interface IIndexPriceTable{
      int TradeId{get;}
      int IndexId{get;}
      double Price{get;}
}

public interface ILegPositionTable{
      int TradeId {get;}
      int LegId {get;}
      int Position {get;}
}

public interface ITradeTable {
      int TradeId{get;}
      int IndexId{get;}
      int LegId{get;}
      //others
}

public interface IJoinedTableRecord : IIndexPriceTable, ILegPositionTable, ITradeTable {
     //Just to put all contracts under one interface and use it as one concrete record, having all information across different tables.
}
Run Code Online (Sandbox Code Playgroud)
  • 为什么我想在我的联合表记录中使用3-TradeId,2-LegId,2-IndexId?

Tom*_*bes 15

解决方案是使用new关键字再次定义属性Percentage,如下所示:

private interface IBase1
{
    int Percentage { get; set; }
}

private interface IBase2
{
    int Percentage { get; set; }
}

private interface IAllYourBase : IBase1, IBase2
{
   new int Percentage { get; set; }
}

private class AllYourBase : IAllYourBase
{
    private int _percentage;

    public int Percentage
    {
        get { return _percentage; }
        set { _percentage = value; }
    }
}

private void Foo()
{
    IAllYourBase iayb = new AllYourBase();
    int percentage = iayb.Percentage; //OK
} 
Run Code Online (Sandbox Code Playgroud)

注意:

接口的C#方法与Bjarne StrouStrup在C++ 14中的方法计划截然不同.在C#中,您必须声明,类通过修改类本身来实现接口,而在C++ 14中,它只需要具有与接口定义相对应的方法.因此,C#中的代码具有更多依赖性,这些依赖性在C++ 14中编码.

  • 由于它没有显示,对于任何好奇 new 关键字是否覆盖 Percentage 的人来说。您还可以将实例转换为 IBase1 和 IBase2 并访问百分比。 (3认同)

And*_*nan 5

因为接口IAllYourBase本身没有声明Percentage属性。

当您将 的实例分配给编译器AllYourBase的变量时IAllYourBase,需要输出对IBase1.Percentage或的调用IBase2.Percentage

callvirt   instance int32 IBase1::get_Percentage()
Run Code Online (Sandbox Code Playgroud)

或者

callvirt   instance int32 IBase2::get_Percentage()
Run Code Online (Sandbox Code Playgroud)

这些是不同类型的不同成员,仅仅因为它们具有相同的签名并不意味着它们可以互换。

在您的现实世界中,您可能需要更细粒度的接口来定义公共属性。