Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't .Net / C# understand interface inheritance with properties of the same name?

Consider the following class and interfaces:

    public interface A { string Property { get; set; } }

    public interface B { string Property { get; set; } }

    public interface C : A, B { }

    public class MyClass : C
    {
        public string Property { get; set; }
    }

Looks simple, right? Now consider the following program:

    static void Main(string[] args)
    {
        MyClass myClass = new MyClass();
        myClass.Property = "Test";

        A aTest = myClass;
        B bTest = myClass;
        C cTest = myClass;

        aTest.Property = "aTest";
        System.Console.WriteLine(aTest.Property);
        bTest.Property = "bTest";
        System.Console.WriteLine(bTest.Property);
        cTest.Property = "cTest";
        System.Console.WriteLine(cTest.Property);
        System.Console.ReadKey();
    }

Looks okay, but it will not compile. It gives me an Ambiguity exception:

Screenshot compiler

Why isn't C# able to figure this out? Is what I'm doing crazy from an architectural point of view? I'm trying to understand the why (I know it can be solved with casting).

EDIT

The problems arose when I introduced interface C. When I use MyClass : A, B I've got no problems at all.

FINAL

Just finised a blog about the subject: Interface Ambiguity and Implicit Implementation.

like image 878
Kees C. Bakker Avatar asked Apr 05 '11 11:04

Kees C. Bakker


2 Answers

In short because it's ambiguous indeed.

Now more detailed story. As you've already seen there is explicit interface implementation, so you can have two different implementations for A.Property and B.Property and when you have only C there is no way you can tell if implementations are the same or not. Since C# "philosophy" is not to guess what you meant, but make you state it more clear when necessary, compiler does not choose either A.Property or B.Property, but reports an error.

like image 165
Konstantin Oznobihin Avatar answered Nov 09 '22 15:11

Konstantin Oznobihin


You need explicit interface implementation:

public interface A { string Property { get; set; } }

public interface B { string Property { get; set; } }

public interface C : A, B { }

public class MyClass : C
{
    string B.Property { get; set; }
    string A.Property { get; set; }
}

When it comes time to call them you are going to have to do:

MyClass c = new MyClass();
Console.WriteLine("Property A is ": ((A)c).Property);

Why don't you do:

public class MyClass : C
{
    string B.Property { get; set; }
    string A.Property { get; set; }
    string B { get { return B.Property; } set { B.Property=value; } }
    string A { get { return A.Property; } set { A.Property=value; } }

}

And it should be noted this is bad design, if you are going to expose an interface C, make sure you find a better way to expose A/B.Property.

like image 32
Nix Avatar answered Nov 09 '22 14:11

Nix