18

I have an abstract class in an API that is used by methods in another assembly. The class has a nested enum defined inside it, a bit like this:

abstract public class Thing
{
    public enum Status { Accepted, Denied, Pending };
    abstract public Status status { get; private set; }
    etc...
}

I then decided it would be a better design if Thing was an interface. But I can't do this:

public interface Thing
{
    enum Status { Accepted, Denied, Pending };
    Status status { get; }
    etc...
}

This produces the error message "Interfaces cannot declare types." However, if I move the definition of the enum outside of the interface, firstly I'd be breaking encapsulation (the Status type really belongs to Thing and is meaningless on its own) and more importantly I would have to go and modify the code in the many other assemblies that use this. Can you think of any solutions?

5
  • If you worried about breaking (You can't encapsulation data members in interfaces by defintion) encapsulation, you should leave Thing as a class. There is nothing wrong with your abstract base class. Commented Feb 21, 2013 at 18:00
  • found some other places where this very question was asked, this comments on this one have some good options. social.msdn.microsoft.com/forums/en-US/csharpgeneral/thread/… basically, you can either declare the enum elsewhere, or use a class instead of an interface....and that's about it. There is no way to do exactly what you are trying to do, mores the pity.
    – Nevyn
    Commented Feb 21, 2013 at 18:01
  • 4
    The "encapsulation" argument doesn't reasonate with me and I would advise you to get rid of the public nested type anyway. If it can be exposed to the world, then treat it as so. Commented Feb 21, 2013 at 18:04
  • Thanks everyone for your useful answers! Commented Feb 22, 2013 at 11:28
  • Notice that you have a public function returning the enum type. Therefore you do not break encapsulation by defining the enum outside the class. Commented Jun 26, 2013 at 12:34

3 Answers 3

20

As the error indicates, you just have to pull the definition of Status outside of the interface. I understand that it breaks encapsulation, but there's really no way around this. I suggest you change the name of Status to something which indicates a strong relation to Thing -- ThingStatus should do the trick.

enum ThingStatus { Accepted, Denied, Pending };

public interface Thing
{
    ThingStatus status { get; }
    etc...
}
5

Oh yes, the solution is to use an abstract class if you need such implementation. Abstract classes are not a bad design and are certainly useful in situations like this.

If you insist on using interfaces, I'm afraid you'd have to go with the solution from p.s.w.g and break a rule or two (those are just guidelines anyway, really).

1

abstract class and interface are different things. abstarct class is abstraction, higher than your domain model and interface is the contract (behavior) of your domain entity. You can use both in your solution as necessary. In concrete scenario status is not behavior it just state of entity. I think abstract class is more reliable choice.

2
  • Thanks for this viewpoint, it's something to think about. As a point of interest, note how abstract classes are used as interfaces in languages that don't have interfaces as part of their syntax (C++ being the obvious example). Commented Feb 21, 2013 at 18:22
  • @KlitosKyriacou Using abstract class as the interface can be achieved by declaring all members as abstract. But this is not exact same in C#. Commented Feb 21, 2013 at 18:26

Not the answer you're looking for? Browse other questions tagged or ask your own question.