What is the difference between an interface and an abstract class for a plugin contract?
Quick Answer
Use an interface for the pure contract that plugins must satisfy — multiple implementations, no shared code, easy to mock. Add an abstract base class when plugins would otherwise duplicate a lot of plumbing (a template-method flow, common validation) — plugins inherit it and override the specific bits.
For a plugin system I'd define an interface as the contract — that's what the host codes against and what a test mocks, and any number of unrelated types can implement it. If I find that every plugin has to write the same boilerplate — the same orchestration steps, the same validation — then I add an abstract base class that implements the common flow as a template method and leaves abstract hooks for the parts that differ. Plugins can inherit the base for convenience or implement the interface directly. The one wrinkle is that adding a method to a published interface used to break everyone, though default interface methods soften that now.
- Common combo:
IPlugin(contract) +PluginBase : IPlugin(optional convenience base). Plugins implement the interface directly or inherit the base. - Evolving an interface used to be a breaking change; C# 8 default interface methods let you add a method with a default body — but use sparingly.
- Abstract class can hold state and constructors; an interface can't (instance state).