Abstract Class VS Interface in C#

/, Best Practices, C#, CodeProject, Design/Abstract Class VS Interface in C#

You can open any C# tutorial and you’ll find some information about abstract classes and interfaces. Most likely, you’ll not find any information about what is the difference between abstract class and interface.
This theme was discussed earlier on the Internet several times but I want to consolidate all the most important thoughts regarding the problem of choosing between an abstract class and interface in this post.

Let’s consider the mechanical and semantic difference between abstract classes and interfaces.
What is an abstract class and what is an interface? The main mechanical difference is that an abstract class can have a default implementation, whereas an interface is just a bunch of member declarations, it defines their signatures. Here is a short example:

public abstract class AlgorithmBase {
    public int Do() {
        int a1 = Operation1();
        int a2 = Operation2();
        return a1 + a2;
    }

    public virtual int Operation1() {
        return 55 ^ 35;
    }

    public virtual int Operation2() {
        return 21 + 48;
    }
}

public interface Algorithm {
    int Operation1();
    int Operation2();
}

Also, you can’t create an instance of an abstract class. So, the mechanical difference is pretty obvious for any meaningful C# developer. Let’s talk about the semantic payload of abstract classes and interfaces.
Very often you can hear that interfaces define contracts. This statement becomes more convincing with the fact that in WCF we treat interfaces and contracts equally. In WCF, a service contract can only be represented by an interface.
In the real world, including the real world outside of programming, contracts have some semantic payload. Usually, they determine some kind of relationships between people, rights, objects and so on. Interfaces have no any semantic payload. They determine nothing except signatures. But signatures don’t bear any significant semantic payload. An interface represents just a shape. Thus, interfaces are not contracts. Here is an example of a contract provided by Krzysztof Cwalina:

public abstract class CollectionContract<T> : IList<T> {
    public void Add(T item) {
        AddCore(item);
        count++;
    }

    public int Count {
        get { return count; }
    }

    protected abstract void AddCore(T item);

    private int count;  
    ...
}

This contract says that when an item is added to the collection, the Count property is incremented by one. In addition, this contract is locked for all subtypes.
Interfaces are made of stone. They can’t be easily changed without breaking existing clients. At the same time, interfaces are easily extendable by clients. A client can extend an interface by extension methods and by the way, if a client wants to implement an interface on a class which already inherits from another class, a client can easily do that, a client couldn’t do that with an abstract class instead of an interface, since multiple inheritance in C# is deprecated.

So, in the end, an interface is more supple from the client’s perspective: any class can implement as many interfaces as it wants to. Unfortunately, an interface is more rigid from the developer’s perspective: it can’t be easily changed and it does not support any kind of reusability.
An abstract class is supple from the developer’s perspective: it supports reusability, it supports encapsulation, it can be extended easily without breaking existing clients.
With all that said, we can conclude the interesting rule of thumb: use abstract classes for building internal APIs and use interfaces for providing external points of extension. Remember, this is not a dogma, this is a rule of thumb.

Look at an example from an open-source project.

public abstract class BitMatrix {
    public abstract bool this[int i, int j] { get; set; }
    public abstract int Width { get; }
    public abstract int Height { get; }

    internal MatrixSize Size {
        get { return new MatrixSize(Width, Height); }
    }

    internal bool this[MatrixPoint point] {
        get { return this[point.X, point.Y]; }
        set { this[point.X, point.Y] = value; }
    }

    internal void CopyTo(SimpleBitMatrix target, MatrixRectangle sourceArea, MatrixPoint targetPoint) {
        for (int j = 0; j < sourceArea.Size.Height; j++) {
            for (int i = 0; i < sourceArea.Size.Width; i++) {
                bool value = this[sourceArea.Location.X + i, sourceArea.Location.Y + j];
                target[targetPoint.X + i, targetPoint.Y + j] = value;
            }
        }
    }

    internal void CopyTo(SimpleBitMatrix target, MatrixPoint targetPoint) {
        CopyTo(target, new MatrixRectangle(new MatrixPoint(0, 0), new MatrixSize(Width, Height)), targetPoint);
    }
}

public abstract class SquareBitMatrix : BitMatrix {
    private readonly int m_Width;

    protected SquareBitMatrix(int width) {
        m_Width = width;
    }

    internal static int GetWidthByVersion(int version) {
        return 17 + 4 * version;
    }

    public override int Height {
        get { return Width; }
    }

    public override int Width {
        get { return m_Width; }
    }
}

The BitMatrix is an abstract class which exposes a lot (not so much in fact, but considerable amount) of reusable code. The SquareBitMatrix overrides the Width and Height and reuses the base class logic.
I’ll not provide code examples of interfaces from BCL, just recall that BCL provides ICollection, IList, INotifyPropertyChanged and tons of other interfaces. This is done so because the extensibility from the client’s perspective is more important in these cases.

This will be a series of articles directly connected with my new course on the subject of “Designing and Implementing API in C#”. Look into that article about my new course and join my mailing list in order to get maximum possible discounts on my programming video courses.

By |2016-07-23T15:40:21+00:00July 22nd, 2016|.NET, Best Practices, C#, CodeProject, Design|5 Comments

About the Author:

I'm thankful enough for that I love what I do. I began my career as a postgraduate student participating in Microsoft ImagineCup contest. I've been working with .NET platform since 2003. I've been professionally architecting and implementing software for nearly 7 years, primarily based on .NET platform. I'm passionate about building rich and powerful applications using modern technologies. I'm a certified specialist in Windows Applications and Service Communication Applications by Microsoft. "If it's work, we try to do less. If it's art, we try to do more." - Seth Godin. What I can say is that software is my art.