16

Today I happens to find that one C# class can inherit one interface both in implicit and explicit way. This surprises me. If C# works in this way, then one instance can behave differently when referenced in different way.

interface IFoo
{
    void DoSomething();
}

class Foo : IFoo
{
    #region IFoo Members
    public void DoSomething()
    {
        Console.WriteLine("do something implicitly");
    }
    #endregion

    #region IFoo Members
    void IFoo.DoSomething()
    {
        Console.WriteLine("do something explicitly");
    }
    #endregion
}


        Foo f = new Foo();
        f.DoSomething();

        ((IFoo)f).DoSomething();

Above code runs and output

do something implicitly
do something explicitly

I believe that this design of C# make inconsistency of behavior. Perhaps it is mandatory that one C# class can inherit from one interface in implicit or expliict way, but not both.

Is there any reason that why C# is designed in such a way?

Rytmis
  • 31,467
  • 8
  • 60
  • 69
Morgan Cheng
  • 73,950
  • 66
  • 171
  • 230

5 Answers5

13

Every class that implements an interface has a mapping between that class's members and the interface's members. If the class explicitly implements an interface member, then the explicit implementation will always be mapped to the interface. If there isn't an explicit implementation then an implicit implementation is expected, and that one will be mapped to the interface.

When a class has the same member name and associated types as an interface but it also explicitly implements the corresponding member for the interface, then the class's "implicit" implementation isn't considered an implementation of the interface at all (unless the explicit implementation calls it).

In addition to different meanings in each case where the class implements multiple interfaces with the same member name/types, even with only one interface, the class itself is considered to have an implicit interface which might have the same member/types as the sole interface but still mean something different.

Mark Cidade
  • 98,437
  • 31
  • 224
  • 236
  • Is this implicit interface an actual interface, or simply the class exposing an interface, i.e. is it a type, albeit a hidden one? – ProfK Oct 31 '08 at 13:18
  • I'm just refering to whatever the class exposes. The CLR doesn't diferrentiate between a class's implementation and its inherent interface (i.e., you can't implement another class's interface and substitute for it unless the interface is a seperately defined Interface type). – Mark Cidade Oct 31 '08 at 16:20
11

Your example does not implement IFoo both implicitly and explicitly. You only implement IFoo.DoSometing() explicitly. You have a new method on your class called DoSomething(). It has nothing to do with IFoo.DoSomething, except that it has the same name and parameters.

Hallgrim
  • 15,143
  • 10
  • 46
  • 54
  • And how would it be implicitly implemented? – Leandro López Oct 31 '08 at 10:45
  • So, "C# class can inherits one interface in both implicit and explicit way at same time" is actually a illusion. One class can inherit one interface once actually. – Morgan Cheng Oct 31 '08 at 11:12
  • yes, see my answer about interface maps: http://stackoverflow.com/questions/253058/why-can-a-c-class-inherit-from-one-interface-both-implicitly-and-explicitly#253073 – Mark Cidade Oct 31 '08 at 16:21
7

This makes it more flexible for when there are collisions. In particular, look at IEnumerator and IEnumerator<T> - they both have a Current property, but of different types. You have to use explicit interface implementation in order to implement both (and the generic form extends the non-generic form).

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • IIRC this is the exact example Jeff Richter uses for EIMIs in the awesome CLR via C#. – Quibblesome Oct 31 '08 at 10:38
  • It's probably the one that comes up most often by a massive factor :) – Jon Skeet Oct 31 '08 at 10:44
  • I've also had the "this[string]" property come up in this scenario. I had a class with a string indexer, and then wanted to implement IDataErrorInfo. Same problem - I had to implement the string indexer for the error explicitly. – Matt Hamilton Oct 31 '08 at 11:21
  • this[T] is just syntactic sugar for the class's default property (which is "Items" in C# unless you use a DefaultPropertyAttribute) – Mark Cidade Oct 31 '08 at 16:23
2

Multiple inheritance : What if you derive from two interfaces defining same method for different purposes?

  interface IMoveable
  {
    public void Act();
  }

  interface IRollable
  {
    public void Act();
  }

  class Thing : IMoveable, IRollable
  {
    //TODO Roll/Move code here

    void IRollable.Act()
    {
      Roll();
    }

    void IMoveable.Act()
    {
      Move();
    }
  }
François
  • 935
  • 1
  • 7
  • 11
0

Guys, Thanks for your answers.

It turns out that "C# class can inherits one interface in both implicit and explicit way at same time" is actually a illusion. Actually, one class can inherit one interface for one time.

In the original question, the "DoSomething" method seems "implicitly implement" interface IFoo (the method is actually generated by VS2008), but it is actually NOT. With explicit implementation of interface IFoo, the "DoSomething" method turns to be just normal method which has nothing to do with IFoo except with same signature.

I still believe it is a tricky design of C#, and it is easy to use it mistakenly. Say, I have some code like this

        Foo f = new Foo();
        f.DoSomething();

Now, I want to refactor it to below code. It seems perfectly OK, but the execution result is different.

        Action<IFoo> func = foo => foo.DoSomething();
        func(f);
Morgan Cheng
  • 73,950
  • 66
  • 171
  • 230
  • 1
    It's tricky because one would think that Foo is-an IFoo just like it is a BaseFoo but it's not! A Foo is better thought as hanlding the *role* of an IFoo and when you access a Foo as an IFoo you are changing its *role* and *possibly* its *behavior* as well. – Mark Cidade Oct 31 '08 at 16:27
  • I will actually claim that it is a tricky design of the Foo class to have two different methods with the same name and parameters. Another example thing you can use to confuse people is to use the new keyword as a method modifier. I never use it because it is confusing, but I might have to some day. – Hallgrim Oct 31 '08 at 16:27