Why prefix C# interface names with an “I”

2019-03-09 08:04发布

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.

18条回答
ゆ 、 Hurt°
2楼-- · 2019-03-09 08:43

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".

查看更多
太酷不给撩
3楼-- · 2019-03-09 08:45

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.

查看更多
等我变得足够好
4楼-- · 2019-03-09 08:47

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.

查看更多
等我变得足够好
5楼-- · 2019-03-09 08:47

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.

查看更多
我命由我不由天
6楼-- · 2019-03-09 08:49

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.

查看更多
乱世女痞
7楼-- · 2019-03-09 08:51

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.

查看更多
登录 后发表回答