Why prefix C# interface names with an “I”

2019-03-09 09:02发布

问题:

What is the rationale behind this naming convention?

I don't see any benefit. The extra prefix just pollutes the API.

My thinking is inline with Konrad's response to this related question; the chosen answer of which is mostly what I am asking for here.

回答1:

Its the complete opposite, the naming convention clearly identifies an interface.

For example if you have:

public class Dog : IPet, IMammal
{
    ....

Just from reading it, I can safely assume that IPet and IMammal are probably interfaces.

The .NET CLR allows for single class inheritance. So, if I have a base class..I can only inherit one class from it. Lets change the IPet interface to a base class..our example now becomes

public class Dog : Pet, IMammal
{
    ....

I am inheriting from the Pet class and implementing the IMammal interface.

If we did it what you are suggesting and removed the letter "I" we have this:

public class Dog : Pet, Mammal
{
    ....

Which one is the class I am inheriting from? Which is the interface I am implementing? It gets confusing right? (FYI..you are supposed to put the base class always first, so you could argue that point...but if you are arguing to remove the letter I from prefixing interface names I doubt you follow that practice as well)

As you can see that naming convention easily tells me a lot about my object without me having to investigate further. I can easily see what I am inheriting vs what I am implementing.



回答2:

I also like it cause I can read it as "I verb-behavior" as in "ICanSave" or "IDoDoubleEntry" etc...



回答3:

I think that the IInterface naming convention is silly. It's an example of Hungarian notation, and I subscribe to the school of thought that despises Hungarian notation. If you have an interface with only one implementation that has the same name, consider the possibility that this is a code smell.

However, I still use it, because in this case IInterface is recommended by Microsoft, and "standard is better than better".



回答4:

Why isn't this a function of syntactical highlighting instead of Hungarian notation? Why doesn't the IDE just italicize identifiers that refer to interfaces if it's so important to distinguish between classes and interfaces. I hate putting "" or "m" before fields, "C" before classes, etc. Even worse, it encourages programmers write really bad APIs such as:

public class List : IList

instead of a more reasonable:

public class LinkedList : List
public class ArrayList : List
public class HashList : List

Even the .NET common class authors fell into this trap. A class name should NEVER be the name of the interface with just the "I" removed. The class name should always tell the user how the class differs from other possible implementations of the interface(s). I vote for dropping the stupid "I" for that reason alone.

Also, when I use intellisense, I want to group things by functional area, not whether it's a class or interface. I never think, "I need an interface, not a class." I always think, "I need something that does X".



回答5:

Actually I find it useful to avoid naming clashes, I might for example create a concrete class called Fred that implements IFred



回答6:

If you consider the two "best-practice-aphorisms"

clarity is king

and

noise is bad

there is a conflict between these. The question is: when does clarity become noise?

For me it more noisy (but equally clear) to write Person person = new PersonImpl() than IPerson person = new Person().



回答7:

I always thought it was fun to use verbs for behavioral interfaces. This is a departure from the class naming convention of using nouns, but it allows the class to "speak" to its behavior.

class Dog: IBark

This does not work well for structural interfaces like WCF interfaces, but we don't need to have fun all the time.

to answer your question, think of the I as "implements" So...

class DogDataService : Dog, IDataService

this service class inherits from Dog and implements IDataService

I'm still not really answering your question, but the I is useful because you get naming collisions between namespace, class and interface.

namespace DataService
interface DataService
class DataService: DataService

so we end up with

namespace DataServices
interface IDataService
class DataService : IDataService

I think in reality, it's a sanity convention.



回答8:

It's either that or add "Impl" to the implementation of the interface (argh). I don't have a problem with the "I", it is the simplest and most straightforward naming for an interface.



回答9:

The "I" convention seems to be an old convention that wouldn't be relevant today. Current code editor provides lots of insight about the type you are using, so arguing that It's easier to identify the interface is like asking for a namespace to be prefixed by a "N" because you want to be sure that you will not confound it with a concrete class (prefix with a "C"?).

A convention doesn't mean that It's a good convention. Sometimes, It's just because people get to use it...

Take for example the C# documentation generator: It doesn't care about it... if your interface is not prefixed with a "I" you will still see your interface in the interface part of your documentation. Do you really think that having a prefix "I" for all your interfaces inside the interface section of your documentation is a relevant information and help you to better identify interfaces?



回答10:

It makes it easily identifiable as an interface.



回答11:

The need to differentiate between an interface and a class actually indicates a design flaw. In a well designed application, it will always be clear. A subclass should always be a specialization and classes can only be specialized in one subject, never more.

A class should have a single reason for existence. It should never be required to put secondary roles in a base class. E.g.:

public class XmlConfigurationFile : ConfigurationFile, IDisposable
{
}

public class YamlConfigurationFile : ConfigurationFile, IDisposable
{
}

The first one is a configuration file that is specialized in Xml, the second one is specialized in Yaml. These are also disposable, but that doesn't matter as much. You didn't create these two classes because of a different disposing processes.

Constrast this with:

public class XmlConfigurationFile : IDisposable, ConfigurationFile
{
}

This will tell you that the main purpose a XmlConfigurationFile has, is that it is disposable. That you can use it as a way to represent configuration files is nice, but is secondary.

The problem starts when you create classes that have multiple reasons for existence:

public class MyConfigurationFile : XmlConfigurationFile, YamlConfigurationFile
{
}

Even if XmlConfigurationFile and YamlConfigurationFile would have been interfaces, it still indicates bad design. How can your configuration file be Xml and Yaml at the same time?

If you read through the examples given (here and elsewhere), people always struggle to find a good example of when the I-prefix matters. One of the answers here is:

public class Dog : Pet, Mammal
{
}

This is how this class will look like in an application about pets. A dog's main purpose is being a specialized pet, that can do pet-related things, not that it is a mammal.

public class Dog : Mammal, Pet
{
}

This is how the same class will look like in an application about animal classifications. It is nice to know a dog is a pet, but it's main purpose is being a specialized mammal, that can do mammal-related things.

I think your classes should tell you the correct story about the architecture and domain of your application. Requiring an interface to be prefixed with an 'I' is a technical requirement and doesn't help you to tell your application's story better.

Once you start writing small, dedicated, single-purpose classes, the need for knowing if it implements or extends will automatically vanish.



回答12:

Naming conventions offer the benefit of telling you something about the object before you use it. Naming conventions have been widely used for many years, going all the way back to fortran's insistence that integer values were restricted (if I remember correctly) to variable names like "i" and "j".

Hungariation notation took naming conventions to a whole new ugly level tha described the variable type, whether or not it was a pointer, etc. Many of us who were exposed to lots of code with Hungarian notation developed nervous twitches and verbal stutters.

Prefixing interface names with I is a relatively low-impact, harmless way of identifying that object.



回答13:

TL;DR - Extracting interface IFoo from class Foo is common in SOLID decoupling, especially for Unit Testing purposes

To me the dual convention of class Foo implementing interface IFoo (especially if both are in the same assembly) conveys a specific intention that:

  • Coupling on a dependency to a Foo should always be indirect, through the corresponding IFoo interface (and likely to be injected via an IoC container)
  • The initial design of IFoo is a proprietary, non-reusable interface specifically to allow classes dependent on Foo to mock out this dependency during unit testing.
  • Beyond the above, a reader doesn't need to infer any additional intelligence in the design of the IFoo interface
  • Conversely, if multiple concrete implementation classes of IFoo are required at a later point, that proper interface segregation design will need to be retrofitted into the hierarchy.

Rationale

In order to be able to Mock or Stub out a class, a widely accepted best practice in Unit Testing is to decouple dependencies between classes only via interfaces. This interface decoupling will also be done to classes which would otherwise never had a design requirement for polymorphicism (i.e. only one such implementation would have existed, were it not for the need for unit testing).

As a consequence, the refactoring and reuse of these interfaces (e.g. the Interface Segregation Principal of SOLID) isn't frequently applied to such 'mockable' interfaces - there is often a 1:1 correlation between the public methods, properties and events of a 'mockable' class (Foo) and its decoupled interface IFoo (similar to the COM-era automatic interfaces in VB).

Tools such as VS and Resharper can make extracting such public symbols from a class into a separate interface trivial, as an afterthought.

Further, if we consider that Mocking frameworks like Moq allow definition of implementations of the interface on-the-fly, we need not waste effort naming the concrete test double implementation class.



回答14:

It is just a naming convention so everybody would know if it is an interface or something else it is not mandatory nor by the compiler nor by the IDE but All the interfaces i saw in my entire life starts with the letter I



回答15:

I seems to traditional convention from Hungarian Notation. Interface Naming Guidelines says "Prefix interface names with the letter I, to indicate that the type is an interface." Framework Design Guidelines also says "DO prefix interface names with the letter I, to indicate that the type is an interface."

It is just a coding convention, So it's to hard to determine good or bad. Important things is consistency.



回答16:

Firstly I believe prefixing with I then description is wrong because it means implementations can have a shorter name. IList (intf) -> List. This is an anti-pattern as we all know we should be using intf and probably only concrete types when creating. Don't flame me this is a generalization but the premise is intf only impl rarely. The implementation name should describe how it's implementing the intf or what it's doing. Think intf List, LinkedList which implements List using a linked list. Who cares if it's longer as we should be using List most of the time. If we have a class implementing many intf we probably should not include all the intf as the shadows the real purpose of the class. IN the case something removed without the intf makes sense. Eg ppl call me by name not Person, Sibling, developer etc using my name is the best most descriptive name. I suppose if a class is impl a simple intf then call it Default Intf which makes it on ious this is the default implementation of Intf. Names of classes sHould in the end be human readable and almost a short phrase describing their purpose. Prefix codes etc are not great as we communicate with words not codes. Computers do t cAre what classes are called so why remains is that we name things so the names help us and our colleagues.



回答17:

Most likely its to make it easily identifiable in intellisense, since all the interfaces will clump together. Similar to how I prefix all my UI controls with btn, tb, lb. When intellisense kicks in everything is clumped together in one easy group.



回答18:

With all of the arguments about naming conventions and giving proper names to variables and methods that actually describe what they do...why not just name your interfaces (e.g. PetInterface, PlayerInterface, etc.) and do away with the prefix "I" all together. So what you have to type an additional 9 letters, at least the "I" is removed and we know it is not a class, because it says "Interface".