20

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.

JubJub
  • 1,485
  • 4
  • 13
  • 14

4 Answers4

42

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
  • 303,634
  • 46
  • 339
  • 357
  • 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 Mar 26 '09 at 02:11
  • 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 Mar 26 '09 at 02:30
  • Explicit interface implementation can also be good if it's possible that a derived class' override of a member may wish to return a type which is derived from the base class' implementation. For example, both `CarFactory` and `ICarFactory` may have `MakeCar()` method which returns `Car`, but `FordCarFactory` may want to have a `MakeCar()` method return a `FordCar`. That could often be best handled by having a `protected` virtual `DoMakeCar` method that returns `Car`, and having both `ICarFactory.MakeCar` and a non-virtual `CarFactory.MakeCar` method chain to that. – supercat Apr 15 '13 at 18:14
8

Change your declaration to:

public abstract class AbstractWidget : IDoesCoolThings 
{
    public void DoCool()
    { 
        Console.Write("I did something cool."); 
    }
}
Matthew Murdoch
  • 30,874
  • 30
  • 96
  • 127
Mitch Wheat
  • 295,962
  • 43
  • 465
  • 541
8

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 :

C# Interfaces. Implicit implementation versus Explicit implementation

Community
  • 1
  • 1
J.W.
  • 17,991
  • 7
  • 43
  • 76
  • Thanks for adding the link to the SO question on implicit and explicit implementation ! – hitec Mar 26 '09 at 05:16
1

You should do it this way:

public interface IDoesCoolThings 
{
   void DoCool();
}

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

public class Widget : AbstractWidget, IDoesCoolThings 
{
}

Usage:

var widget = new Widget();
widget.DoCool();
venkat
  • 5,648
  • 16
  • 58
  • 83
Toffee
  • 4,586
  • 2
  • 15
  • 6