为什么我不应该在字段前加上?

时间:2009-03-18 18:30:47

标签: c# field naming-conventions hungarian-notation

我从来都不是匈牙利乐谱的粉丝,除非你做一些非常低级的编程,否则我总觉得它很无用,但在每个C ++项目中,我都采用了某种匈牙利符号政策。强制执行,并使用一些“非真正匈牙利”的前缀作为字段的m_,静态的s_,全局的g_等等。

很快我意识到它在C#中有多么无用,并逐渐开始放弃我所有的旧习惯......但是'm_'的事情。我仍然在私有字段上使用m_前缀,因为我真的觉得能够区分参数,本地和字段非常有用。

naming conventions for fields page at MSDN说我不应该,但它没有说明原因(例如Google的惯例通常会使他们的处方合理化)。

有没有理由我不应该或只是风格问题。如果是后者,前缀通常被认为是一种不好的风格,我是否可以期待其他人在代码库上做出负面反应?

25 个答案:

答案 0 :(得分:51)

我喜欢成员字段的下划线前缀。大多数情况下我喜欢它,因为这样,我的所有成员字段都按字母顺序显示在屏幕顶部向导栏中的方法之前。

WizardBar

答案 1 :(得分:37)

何时应该:

  • 当您的项目编码指南说明您应该

当你不应该:

  • 当您的项目编码指南说您不应该

如果您还没有任何指导方针,您可以自由选择您或您的团队想要的任何内容,并且感觉最舒服。就个人而言,当编写C ++时,我倾向于使用m_作为成员,它确实有帮助。当用其他语言编写代码时,特别是那些没有真正类的代码(如Javascript,Lua),我没有。

总之,我不相信有“正确”和“错误”的方式。

答案 2 :(得分:21)

C#3.0中的自动实现的属性功能不再需要这种约定。而不是写

string m_name;
public string Name { get { return m_name; } }

string _Name;
public string Name { get { return _Name; } }

(或任何其他约定),您现在可以写

public string Name { get; private set; }

由于您不再需要显式的后备存储变量,因此您不再需要为其提供名称;从而避免了整个讨论。

显然,当您真正需要显式支持存储(例如执行验证)时,此参数不适用。

答案 3 :(得分:11)

我已经尝试过m_,s_,只是_,而且根本没有前缀。我已经决定只使用_来表示所有静态和实例变量。我认为区分静态变量和实例变量并不重要。理论上听起来不错,在实践中它不会产生问题。

一位同事曾经做过一个令人信服的论据来消除所有前缀,我们在一个项目上尝试过,它比我预期的更好。我把它带到了我的下一个项目,并对它“干扰”Intellisense感到恼火。当您遇到以下情况时

int foo;
public int Foo
{
  get { return foo; }
}

开始输入foo将建议实例变量和属性。使用下划线对变量进行前缀消除了令人烦恼的双重建议,因此我切换回使用_。

答案 4 :(得分:11)

正如一些人所暗示的那样,MS指南说:

  

不要为字段名称使用前缀。   例如,不要使用g_或s_来   区分静态与非静态   字段。

我碰巧同意这一点。前缀使您的代码看起来很丑陋,浪费空间而且无关紧要。话虽如此,通常使用字段来支持属性,其中字段和属性将具有相同的名称(私有字段为驼峰,属性为pascal情况)。在VB中,这不起作用,因为VB不区分大小写。在这种情况下,我建议使用单个_前缀。不多也不少。它看起来更干净,恕我直言。

答案 5 :(得分:10)

我尝试关注MSDN .NET library guidelines。它们包含naming guidelines部分。

显然,这些是您的项目指南的次要因素。

答案 6 :(得分:10)

我更喜欢标记属性支持字段(虽然已经提到.NET 3.0+减少了对自动属性的需求)带下划线而不是“m”。首先,当我使用它们时,它将它们置于InteliSense列表的顶部。

我承认我需要了解MSDN的指导方针,这些天来事情可能会发生如此迅速的变化。

答案 7 :(得分:9)

使用像resharper这样的工具,真的没有前缀的理由。此外,如果您编写简短的方法,您应该能够非常快速地告诉var的来源。最后,我想我不会真的看到需要区分静态或不静态,因为如果你尝试做一些你无法做的事情,再次resharper就会变成红线。即使没有resharper,你也可能会被编译器保存。

答案 8 :(得分:5)

我总是使用 m _ 为成员变量添加前缀,为 s _ 添加静态变量,原因与您声明的相同。有些人使用下划线为成员变量添加前缀,但我总是发现这有点奇怪(但这只是个人偏好)。

我工作的大多数人都使用m_ / s_前缀。我不认为你使用的东西太重要了,只要你保持一致。

答案 9 :(得分:5)

我从不使用它们。它鼓励草率编码。 MSDN编码指南,就在它的位置。

答案 10 :(得分:4)

以下是使用_(而不是m _)的几个原因。

(1)尽管有MS的命名指南,但很多BCL人都这么做。 (查看他们的blog。)这些人编写框架,因此他们有一些值得复制的好习惯。 MSDN上的一些最有用的示例代码是由它们编写的,因此使用下划线约定。这是一个事实上的行业标准。

(2)单个下划线是一种明显但不显眼的方法,通过简单地读取源来消除方法和类级变量的歧义。它可以帮助人们在阅读时理解新的(或旧的)代码 一目了然 。是的,您可以将鼠标悬停在IDE中查看,但我们不应该被强制使用。你可能想在文本编辑器中阅读,或者我敢说,在纸上。

(3)有人说你不需要任何前缀,因为方法会很短,稍后如果需要你可以将字段更改为自动实现的属性。但在现实世界中,方法只要它们需要,并且字段和属性之间存在重要差异(例如序列化和初始化)。

脚注:m_中m成员的“m”在我们的使用中是多余的,但它是小写的,因为许多这些旧命名约定中的一个想法是以大写字母开头的类型名称,实例名称以小写。这不适用于.NET,因此它是多余的。匈牙利语符号有时也适用于旧的C编译器(例如整数或指针转换和算术),但即使在C ++中,在处理类时它的用处也会减少。

答案 11 :(得分:3)

@John Kraft提到,没有“正确”的答案。 MattJ是最接近的 - 你应该始终遵循公司的风格指南。在罗马时,以及所有这些。

至于我个人的意见,因为这里需要它,我投票说你完全放弃了m_

我认为最好的风格是所有成员都是PascalCased,无论可见性如何(即使是private成员),所有参数都是camelCased。我不打破这种风格。

我可以理解为属性后备存储字段添加前缀的愿望;毕竟你必须区分领域和财产,对吧?我同意,你必须。但是使用后期修复。

使用m_MyProperty而不是_MyProperty(甚至MyPropertyValue,我曾见过甚至曾经提升过一次。它更容易阅读和理解 - 更重要的是 - 它与intellisense中的原始属性名称相近。

最终,这就是我更喜欢后缀的原因。如果我想使用intellisense访问MyPropertyValue,您(通常)会输入“My <down-arrow> <tab>”,因为那时您已足够接近,只有MyPropertyMyPropertyValue在列表中。如果您想使用intellisense访问m_MyProperty,则必须输入“m_My <tab>”。

在我看来,这是关于击键经济的。

答案 12 :(得分:3)

我从来没有这样做,原因是我[尽量]保持我的方法简短。如果我能在屏幕上看到整个方法,我可以看到参数,我可以看到当地人,所以我可以告诉我们这个类拥有什么,什么是参数或本地。

我通常使用特定符号命名我的参数和当地人,但并非总是这样。如果不是不一致,我什么都不是。我依赖于这样一个事实,即我的方法很短,并且当它们应该只做X时,试图阻止它们做X,Y和Z.

无论如何,这是我的两分钱。

答案 13 :(得分:3)

C ++和C#之间有一个重要的区别:工具支持。当您遵循既定指南(或常见变体)时,您将获得C ++从未拥有的深层次工具支持。遵循标准允许工具进行更深入的重构/重命名操作,而不是你能够做到的。 Resharper这样做。所以坚持一个既定的标准。

答案 14 :(得分:3)

除非我坚持使用vi或Emacs编辑代码,否则我的IDE会为我提供不同的成员显示,因此我很少使用任何特殊约定。这也适用于带I的接口或带C的类。

请有人在接口上解释I-prefix的.NET风格。 :)

答案 15 :(得分:3)

我习惯的是,私有财产得到了一个小的下划线f.ex“string _name”。公众得到了“名字”。方法中的输入变量得到小写字母“void MyMethod(string name)”。

如果你得到静态常常用大写字母写。 static const MYCONST = "hmpf"

答案 16 :(得分:2)

每当我做出选择时,我都不会使用任何匈牙利疣。这是额外的打字,并没有传达任何有意义的信息。任何好的IDE(我根据此功能的存在定义“好”)将允许您对静态成员,实例成员,成员函数,类型等具有不同的语法突出显示。没有理由混淆您的包含可由IDE提供的信息的代码。这是因为您的版本控制系统应该对这些内容负责,因此不会使用已注释掉的旧代码来混淆您的代码。

答案 17 :(得分:2)

最好的方法是与同事达成一致,并坚持下去。它绝对不一定是最适合每个人的方法,只是同意一种方法比你实际同意的方法更重要。

我们为代码标准选择的是使用_作为成员变量的前缀。其中一个原因是它可以很容易地在intellisense中找到局部变量。

在我们同意该标准之前,我使用了另一个标准。我根本没有使用任何前缀,并在代码中写了this.memberVariable来表明我正在使用成员变量。

使用C#3中的属性简写,我发现我使用了很少的显式成员变量。

答案 18 :(得分:2)

答案 19 :(得分:2)

我不再使用那种风格了。它的开发是为了帮助您快速了解变量的使用方式。较新的开发环境允许您通过将鼠标悬停在变量上来查看该信息。如果您使用这些新工具,它的需求已经消失。

答案 20 :(得分:2)

C / C ++中的符号的好处是可以更容易地查看符号的类型,而无需搜索声明。这些样式出现在Intellisense和“Go to Definition”之前 - 我们经常不得不继续寻找知道有多少头文件的声明。在一个大型项目中,这可能是一个非常令人烦恼的问题,在查看C源代码时非常糟糕,但在使用混合程序集+源代码和原始调用堆栈进行取证时更糟糕。

当面对这些现实时,使用m_和所有其他匈牙利规则即使在维护开销时也会开始有意义,因为在查看不熟悉的代码时,只需查看符号的类型就可以节省多少时间。现在我们当然有Intellisense和“Go to Definition”,因此该命名约定的主要时间节省动机不再存在。我不认为这样做有多大意义,我通常会尝试使用.NET库指南,以保持一致,并可能获得更多的工具支持。

答案 21 :(得分:1)

与官方指南最接近的是StyleCop,这是Microsoft的一个工具,可以自动分析您的源文件并检测推荐编码风格的违规行为,并且可以在Visual Studio和/或自动构建中运行作为MSBuild。

我们在我们的项目中使用它,它确实有助于使开发人员之间的代码风格和布局更加一致,但是要注意它确实需要相当一些习惯!

回答你的问题 - 它不允许任何匈牙利表示法,也不允许任何前缀如m_(事实上,它根本不允许使用下划线)。

答案 22 :(得分:1)

C ++编码标准 Sutter,Herb Alexandrescum Andrei ,2004)中可能会有一些见解。项目#0的标题是“不要让小东西流汗。(或者:知道什么不要标准化。)”。

他们稍微触及这个具体问题,说“如果你不能决定你自己的命名惯例,试试......私人成员变量喜欢这个_ ......”(记得使用前导下划线受C ++中非常具体的规则约束。

然而,在到达那里之前,他们强调一定程度的一致性“......重要的是不要设定规则,只是为了与文件中已经使用的风格保持一致......”

答案 23 :(得分:0)

如果您不按照特定指南进行编码,则应继续使用实际的m_表示法,并在项目编码指南如此说明时进行更改。

答案 24 :(得分:0)

功能齐全。

  • 不要使用全局变量。
  • 不要使用静态变量。
  • 不要使用成员变量。

如果您真的需要,但只有在必须时,才使用一个且只有一个变量来访问您的应用程序/环境。