.NET中接口的“ I”前缀命名约定背后的原因是什么?


10

我知道自COM以来就存在“ I”约定,但是我从未理解为什么没有像.NET之前的所有其他命名约定一样重新考虑它。

从消费角度来看,将接口与例如抽象类分开的唯一一件事是它们可以被多重继承。但是Visual Studio 2003之后的所有内容都在工具提示中显示了类型签名,因此,它与所有其他已废弃的匈牙利符号一样没有用。

我还认为可能是这样,您可以使用相同的名称对接口进行基本实现,例如Message继承IMessage,但是大多数.NET库都去掉了在末尾添加“ Base”一词(例如System.Collections.ReadOnlyCollectionBase),这在语义上更具意义。

COM互操作似乎是另一个可能的原因-但它生成的包装器类并非完全是惯用的.NET,因此我怀疑这是一个美学考虑。

在我的一个较新项目中,我完全放弃了惯例,感觉还不错。有什么我想念的吗?


1
您不会继承接口来实现它们,这有很大的不同。
丹尼尔·利特尔

也似乎像IList和List这样的偏好,而不是List和ArrayList。他们可能这样做是因为IList不是ListBase,但实际上是ListInterface(不是Type接口的List),如果您明白我的意思的话。
丹尼尔·利特尔

@Lavinski在.NET中IListList序列的,连续的,随机访问,增长集合的通用术语。我认为F#的别名List正确ResizeArray;这绝对是一个更具描述性的名称。IList然后可能是List,所以这似乎也不是原因。
宫坂丽

2
IBaseBall和IBaseBallBase对我而言比BaseBallBase和BaseBallBaseBase更有意义(愚蠢的示例,我知道:D)
e-MEE

@ e-MEE同样愚蠢的是IIRC,它可能是IRC聊天协议的接口,或者是“如果我没记错的话”的缩写。
宫坂丽

Answers:


12

我认为这可能是前缀有用的唯一情况。

类和接口确实具有不同的语义,并且由于它们都是类型,因此很容易混淆。
当我看到类声明时,我可以立即说出它的派生实现的内容

public sealed class ActivityCollection : List<Activity>, 
    IList<Activity>, ICollection<Activity>, IEnumerable<Activity>, 
    IList, ICollection, IEnumerable

如果定义看起来像这样,将很难理解

public sealed class ActivityCollection : ListClass<Activity>, 
    List<Activity>, Collection<Activity>, Enumerable<Activity>, 
    List, Collection, Enumerable

那你怎么打ListClass?显然,这不仅仅是ListBase因为它可以单独使用。
因此,我们要么必须解决刚刚发明的问题,要么改编前缀以将类与接口分开,.NET Framework设计人员就是这样做的。

另外,就我个人而言,当我可以从方法签名中得知它可以与接口一起使用时,我发现它很有用。

public void PrintLines (IEnumerable<string> source)

这就像一个信号在我的头上:嘿,我可以实现!无论合同如何,我都可以提供该方法。

当然可以说这并不重要,但这是使前缀值得我使用的那些小事情之一。当您经常使用接口并需要轻松区分两者时,在使用IoC容器编写大量代码时,此功能特别有用。

顺便说一句,.NET类型系统中不仅接口具有前缀。不要忘记泛型类型参数:

public delegate TResult Func<in T, out TResult>(
    T arg
)

当能够区分类和另一种类型非常有用时,这是另一种情况。


2
通过知道“第一类是继承,第二类是接口”,您可以轻松地理解这一点。
2011年

3
这似乎是一个合理的原因。Java的似乎简单地使用关键字来澄清清单多一点很好地解决了这个问题:class Dog extends Mammal implements MailmanChaser。@Saeed,您可以拥有一个不继承任何东西的类,因此列表中的第一个类型实际上是接口而不是基类。
宫坂丽

粗体部分为+1,尽管我可以想到另一个基于前缀的约定会有所帮助的地方:区分封装了int[](或可变类型的其他对象)专有所有权的字段,该字段可以更改但不能共享,并且封装了int[]该共享的所有权,即使其类型允许更改,也不允许任何人进行更改。
超级猫

6

我认为您不会丢失任何东西,这只是一种历史习惯。

我也同意您的看法,并且还对几个中小型项目放弃了“我”,但没有不利影响。


2
但是,很奇怪的是,除此公约外,他们几乎淘汰了所有其他过时的公约。历史也不能完全解释它。我仍然觉得一定有一个原因,除非这真的只是内部政治-但即使如此,我仍然看不到有人会对我被抛弃感到不高兴的原因。
宫坂丽

2

我认为,根据Microsoft关于接口和类的命名准则,唯一的原因是,有时您在接口名称和实现该名称的类之间会有冲突。这可以回溯到以下事实:接口实际上是框架,而不是实质,而实现者类实际上是主体(实现蓝图)。因此,IAnimal仅描述动物应该拥有的东西,而Animal可以告诉您它拥有什么。

不过,我个人完全同意你的一点是,我们可以简单地使用动物基地的接口,以及动物的类。

另一方面,有时两件事之间的冲突是如此之大,以至于尽管已经做出了决定,一个团队还是决定提供一个公约以防止进一步的冲突。例如,在ASP.NET MVC中,局部视图布局(母版页)就像普通的View一样,但是它们具有不同的功能。因此,微软尽管在命名强调不使用下划线的,建议以下划线布局局部视图以下划线。


出了什么问题AnimalInterface,而不是AnimalBase?它不是基类,而是接口。
Scott Whitlock

3
但是IAnimal而不是AnimalInterface有什么问题?确保我们已经从头到尾进行了探索-这只是表明某些“匈牙利”符号很有用。将它们全部扔掉(I和T除外),比起寻求更好的系统的周全尝试,更加激怒。
gbjbaanb

2
@ScottWhitlock:对我来说,IAnimal比更具可读性AnimalInterface。除了可以将简单的简短约定用于经常出现的情况之外,最好使用详细名称。接口就是这种情况。
maaartinus
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.