views:

1410

answers:

3

I'm learning C# coming from C++ and have run into a wall.

I have an abstract class AbstractWidget, an interface IDoesCoolThings, and a class which derives from AbstractWidget called RealWidget:

public interface IDoesCoolThings
{
    void DoCool();
}

public abstract class AbstractWidget : IDoesCoolThings
{
    void IDoesCoolThings.DoCool()
    {
        Console.Write("I did something cool.");
    }
}

public class RealWidget : AbstractWidget
{

}

When I instantiate a RealWidget object and call DoCool() on it, the compiler gives me an error saying

'RealWidget' does not contain a definition for 'DoCool'

I can cast RealWidget object to an IDoesCoolThings and then the call will work, but that seems unnecessary and I also lose polymorphism (AbstractWidget.DoCool() will always be called even if i define RealWidget.DoCool()).

I imagine the solution is simple, but I've tried a variety of things and for the life of me can't figure this one out.

+13  A: 

You're running into the issue because you used explicit interface implementation (EII). When a member is explicitly implemented, it can't be accessed through a class instance -- only through an instance of the interface. In your example, that's why you can't call DoCool() unless you cast your instance to IDoesCoolThings.

The solution is to make DoCool() public and remove the explicit interface implementation:

public abstract class AbstractWidget : IDoesCoolThings
{
    public void DoCool()      // DoCool() is part of the abstract class implementation.
    {
        Console.Write("I did something cool.");
    }
}

// ...

var rw = new RealWidget();
rw.DoCool();                  // Works!

In general, you use EII in two cases:

  • You have a class that must implement two interfaces, each of which contains a member that has an identical name/signature to another member in the other interface.
  • You want to force clients not to depend on the implementation details of your class, but rather on the interface that's being implemented by your class. (This is considered a good practice by some.)
John Feminella
it's amazing the difference 15 seconds can make!
Mitch Wheat
God, I thought I'd tried that. Thanks! I seemed to have missed this key line in my reference book: "a method defined by using explicit interface implementation cannot be declared as virtual, whereas omitting the interface name allows this behavior."
JubJub
I was confused that simply making the method public in the abstract class didn't fix the problem, plus the examples I read didn't define methods as public or private, so I came to believe interface methods are implicitly public and virtual. Overall, an embarrassing question :). Thanks though!
JubJub
+4  A: 

Chnage your declaration to:

public abstract class AbstractWidget : IDoesCoolThings 
{
    public void DoCool()
    { 
        Console.Write("I did something cool."); 
    }
}
Mitch Wheat
+4  A: 

The way you implement the interface is explicit implement void IDoesCoolThings.DoCool(), if you choose implicit implement interface.

public abstract class AbstractWidget : IDoesCoolThings
{
    public void DoCool()
    {
        Console.Write("I did something cool.");
    }
}

Then it will work.

Read this :

http://stackoverflow.com/questions/143405/c-interfaces-implicit-and-explicit-implementation

J.W.
Thanks for adding the link to the SO question on implicit and explicit implementation !
hitec