21

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.

2
  • To have polymorphism in widgets' DoCool(), you'd need to declare the AbstractWidget's one virtual. Commented Mar 26, 2009 at 2:06
  • Erg. I'd read somewhere that virtual was implied for interface methods. Commented Mar 26, 2009 at 2:23

4 Answers 4

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.)
Sign up to request clarification or add additional context in comments.

3 Comments

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."
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!
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.
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

1 Comment

Thanks for adding the link to the SO question on implicit and explicit implementation !
8

Change your declaration to:

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

Comments

3

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();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.