Idiomatic C# and the “I” Prefix

In a prior blog post ( I mentioned a for-fun side project I’ve been working on. I also mentioned that I’d share some lessons learned in a subsequent blog posts… so here we are!

I planned on rolling up a number of lessons learned in one post but realized it would be too long. Plus I like Bertrand Le Roy’s idea of applying the Single Responsibility Principle to blog posts so let’s hone in on one specific topic:

Using the “I” Prefix for Interface Names in .NET

In “Clean Code” by Uncle Bob Martin, he recommends not using the “I” prefix for interface names. He contends that if you cannot come up with a descriptive enough implementation name then an “Impl” (for implementation) suffix is still better than an “I” prefix (i.e. ThingDoerImpl is better than IThingDoer). While the book is written primarily from a Java perspective, I thought I’d try it out on a .NET project knowing that this was very much contrary to a long-standing C# convention. After about 5 months of developing without the “I” prefix, below are my takeaways on the good and the bad.

Reasons to Drop The “I” Prefix

Better Implementation Names – Not having the “I” prefix helped force me to come up with better names for my implementations. For example, instead of just having IThingDoer (interface) and ThingDoer (implementation), I would instead try to go with something like ThingDoer (interface) and ThingDoerThatDoesItACertainWay (implementation). If I was really not feeling inspired I would default to ThingDoer and ThingDoerImpl (implementation). While this isn’t great, it at least allowed me to not to have to add the “I” prefix.

Related Files Grouped Together – With the “I” prefix, your interface and implementation are usually not grouped together in Visual Studio’s Solution Explorer. In your IDE you end up with something like the below (alphabetical ordering):

At least if you don’t have the “I” prefix you’ll have the slightly more convenient:

Reasons To Use the “I” Prefix

Visual Studio Solution Explorer Doesn’t Distinguish Between Classes and Interfaces by Default – While the Class View in Visual Studio clearly calls out interfaces vs. implementations, the Solution Explorer does not — presumably because you can have both classes and implementations in a single .cs file (although I prefer to never do this). This means that a clear naming convention (i.e. the “I” prefix) is the only easy way to tell if a file represents a class or an interface.

Unable To Distinguish Between Implementing Interface and Extending a Base Class – In C# the colon (“:”) is used to denote both implementing interfaces as well as extending base classes. In Java you have the “extends” and “implements” keywords to help distinguish between classes as interfaces when you are defining your inheritence. For example, in java you could have:

public class SomeClass extends SomeBaseClass implements SomeInterface

In C# you would just have:
public class SomeClass : SomeBaseClass, SomeInterface

Without a clear naming convention to call out the base class vs. the interface you might not be able to easily tell which is which. Take for example:public class SomeClass : LemonSlicer, ApplePeeler

Are these interfaces or classes? Or is LemonSlicer a base class and ApplePeeler is an interface?

Long Standing Convention – As much as I don’t like to give this as a reason, one cannot overlook the fact that the “I” prefix is a convention that all C# developers understand and expect. While I was getting pretty comfortable without the “I” prefix in my own code (with which I was obviously very familiar), other developers were confused and frustrated when trying to work with the code. Given that I’d actually like other people to help me with my project this is pretty much the deal-breaker.


Dropping the “I” prefix wasn’t nearly as painful as I thought it would be. It forced me to pick better names for my implementations and I found the grouping of files to be more convenient in the Visual Studio Solution Explorer. However, the simple fact that developers expect the “I” prefix is probably a good enough reason to keep with the status quo — which I’ll be doing from here on out.

What do you think?