Static Interface Methods in C#

"There are only two hard things in Computer Science: cache invalidation and naming things." - Phil Karlton

I cannot comment too much on the first "hard thing" mentioned by Phil Karlton, but the issue of naming things is something I can relate to. Choosing right (descriptive, sensible, yet concise) names for classes, methods and variables can be hard; so much more when your programming language of choice gets in the way of what you're trying to achieve.

Image that we're building a system that extracts text from audio files provided in different formats. We've designed an interface for our extractor classes with a method name that is sitting just right:

After implementing the underlying classes we realize that we would actually like to call the method statically in the cases where we work directly off the implementation type. So assuming we have a class declaration of:

public class Mp3TextExtractor : IAudioTextExtractor

Instead of having to type:

var content = new Mp3TextExtractor().Extract(@"C:\TEMP\audio.mp3");

We would much rather use the method as follows:

var content = Mp3TextExtractor.Extract(@"C:\TEMP\audio.mp3");

When I came across a similar scenario in a project recently, I found that C# does not allow static methods to implement an interface. Meaning, implementing the Execute method statically is not allowed:

Faced with this scenario, we have some options:

  1. Get rid of the interface.
  2. Implement the interface, but add another method (e.g. Extract_Static).
  3. Implement the interface, but hide the interface method behind a public static version.

With option 1 we loose some powerful advantages of using interfaces, such as how it aids with decoupling (great for unit testing) and the ability to build things like the following:

Option 2 is a viable option, but in my opinion it opens the door to some ugly method naming (providing a case for the argument I made at the start of the post).

In opting for option 3, we may be able to have our cake, and eat it. It means that our class that implements the interface needs to be updated as follows:

This implementation allows the Extract method to be called as:

var content = Mp3TextExtractor.Extract(@"C:\TEMP\audio.mp3");

As well as:

IAudioTextExtractor extractor = new Mp3TextExtractor();
var content = extractor.Extract(@"C:\TEMP\audio.mp3");

The compromise when using this option is that calling the method directly from a class instance is not allowed (resulting in a compiler error):

Mp3TextExtractor extractor = new Mp3TextExtractor();
var content = extractor.Extract(@"C:\TEMP\audio.mp3");

However, seeing that this type of usage is what we were trying to avoid in the first place, I think this has positioned the solution much better in terms of utilizing the power of interfaces, while allowing using the method in a clean way through a static method call without having to resort to ugly and confusing method naming.