Probably the most C# common interview question in London is “What’s the difference between an abstract class and an interface?”. Let’s be clear: if you use the word contract in your answer, you’re not getting a job if I’m asking the question. Contracts are a concept that doesn’t directly correspond to any code construct in C#, abstract classes and interfaces are your fundamental building blocks of well written code.
Here’s the one word answer: Code. Abstract classes can have code, interfaces can’t. C#, like Java, doesn’t allow you to pull code from two sources, so you can only inherit from one abstract class. Equally, the very presence of code tends to form a template for inheritors, which can be good or bad depending on context.
Most people think of abstract classes as producing more fragile solutions than interfaces, simply because more decisions are made up front. That’s true in the case of a parameter that’s an abstract class, but actually the opposite is true when you choose to inherit from an interface.
Here’s the problem: what happens when add a method to the interface? As Erich Gamma discusses here, every implementation breaks. That’s not so bad if every class that implements the interface is actually loaded into Visual Studio: then you can just fix them. On the other hand, if you’ve not got your entire code-base loaded or, worse, you’re writing a framework, you’ve got broken code on your hands.
If everyone inherits from an abstract, the new method can be added to the abstract class without breaking any inheritors. Now you know why Microsoft are so fond of abstract classes.
The Third Way
The thing with abstraction is, you can to some extent have your cake and eat it too. Just because you create an IGraph interface doesn’t mean you can’t also create a PureBaseGraph abstract class with no implementation of any of the methods. You’ve got the ultimate flexibility of the interface, but you can choose convenience and stability of an abstract class. Microsoft don’t favour this approach, because they know that when they change an interface they’ll be deluged with complaints from developers who don’t want to ever change their code. NHibernate and Castle Windsor, on the other hand, do, as Oren outlines here. Using EmptyInterceptor avoids being exposed to changes in the interface, but you can run with scissors if you really want.
So, do I get the job?