Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why implementing multiple interfaces with same property shows 'ambiguity' warning?

Related Post: C# interface method ambiguity

Code from the same source:

    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. 
    } 

(But does not answer my question -- "WHY the contracts become ambiguous? " )

Given:

Interface is a contract that the implementing class MUST abide with.

If two (or more) interfaces ask for the same contract and a interface passes them 'forward' and then class implements both of them and ACCEPTS that the common contracts should serve as just one contract for the implementing classes (by not providing an explicit implementation). Then,

  1. Why does compiler shows 'ambiguity' warning over the common contracts?

  2. Why the compiler fails to compile on trying to access the ambiguous contract through interface( iayb.Percentage) ?

I would like to know what benefit compiler is serving with this restriction?

Edit: Providing a real world use case where I would like to use contracts across interfaces as one contract.

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.
}
  • Why would I like to have 3-TradeId, 2-LegId, 2-IndexId in my joined table record?
like image 654
Manish Basantani Avatar asked Mar 12 '12 03:03

Manish Basantani


People also ask

What happens when a class implements two interfaces having the same method name?

A class implementation of a method takes precedence over a default method. So, if the class already has the same method as an Interface, then the default method from the implemented Interface does not take effect. However, if two interfaces implement the same default method, then there is a conflict.

Can two interfaces have same method implementation?

No, its an errorIf two interfaces contain a method with the same signature but different return types, then it is impossible to implement both the interface simultaneously.

Can an object have multiple interfaces?

A class or struct can implement multiple interfaces. A class can inherit a base class and also implement one or more interfaces.

Can we implement multiple interfaces in C#?

C# allows that a single class can implement multiple interfaces at a time, and also define methods and variables in that interface.


2 Answers

The solution is to define a property Percentage again with new keyword like this:

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
} 

Notice:

C# approach to interfaces is very different to approach plan by Bjarne StrouStrup in C++14. In C# you have to claim, that the class implement interface by modifying class itself while in C++14 it only needs to have methods which correspond to interface definition. Thus the code in C# have more dependencies that code in C++14.

like image 94
Tomas Kubes Avatar answered Nov 16 '22 02:11

Tomas Kubes


Because the interface IAllYourBase does not declare the Percentage property itself.

When you assign an instance of AllYourBase to a variable of IAllYourBase the compiler needs to output a call to either IBase1.Percentage or IBase2.Percentage:

callvirt   instance int32 IBase1::get_Percentage()

or

callvirt   instance int32 IBase2::get_Percentage()

These are different members on different types and just because they have the same signature doesn't mean they are interchangeable.

In your real world situation you might need finer grained interfaces that define the common properties.

like image 30
Andrew Kennan Avatar answered Nov 16 '22 02:11

Andrew Kennan