views:

1134

answers:

5

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?

+12  A: 

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
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
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
+2  A: 

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
+4  A: 

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
IIRC this is the exact example Jeff Richter uses for EIMIs in the awesome CLR via C#.
Quibblesome
It's probably the one that comes up most often by a massive factor :)
Jon Skeet
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
this[T] is just syntactic sugar for the class's default property (which is "Items" in C# unless you use a DefaultPropertyAttribute)
Mark Cidade
+9  A: 

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
And how would it be implicitly implemented?
Leandro López
only if there wasn't already an explicit implementation
Mark Cidade
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
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
A: 

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