Click here to Skip to main content
15,891,855 members
Articles / Programming Languages / C#

Abstract Class Vs Interface in C#

Rate me:
Please Sign up or sign in to vote.
4.91/5 (6 votes)
22 Jul 2016CPOL3 min read 12.3K   5   1
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:

C#
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 do not have 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:

C#
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.

C#
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 article was originally posted at http://www.engineerspock.com?p=1875

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



Comments and Discussions

 
QuestionI like where you are going with this but... Pin
PureNsanity28-Jul-16 4:19
professionalPureNsanity28-Jul-16 4:19 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.