为什么不应该给我的字段添加前缀?

49

我从来不喜欢匈牙利命名法,除非你在做一些非常底层的编程,否则我一直觉得它没什么用,但在我参与的每个C++项目中都执行了某种形式的匈牙利命名策略,其中包括使用一些“不是真正的匈牙利命名法”前缀,例如m_表示字段,s_表示静态,g_表示全局等。

后来我意识到在C#中它有多么无用,并逐渐放弃了所有旧习惯... 但是'm_' 还在使用。 我仍然在私有字段上使用 m_ 前缀,因为我真的发现这非常有用,可以区分参数、本地变量和字段。

MSDN上的字段命名约定页面说我不应该这样做,但没有说明为什么(例如Google的约定通常倾向于理性化他们的规定方式)。

是否有不允许我这样做的原因,还是只是一个风格问题?如果是后者,那么前缀通常被认为是一种不良风格吗?我能否期望其他人在工作中对代码库作出负面反应?


7
这个话题在论坛上已经被多次讨论过了。这是一个宗教性的辩论,你永远不会找到一个“正确”的答案。 - John Kraft
根据其中一个答案,关于样式的MSDN文章是由Brad Adams撰写的。他在博客中解释了命名规则:“扩展公共规则(无匈牙利语法,无成员变量前缀等)的原因是为了产生一致的源代码外观。此外,目标是拥有干净易读的源代码。代码可读性应该是主要目标。” http://blogs.msdn.com/b/brada/archive/2005/01/26/361363.aspx - user7610
1
微软的.NET 命名指南(由Visual Studio的代码分析工具强制执行)不要求私有类型和成员遵循规范:“尽管采用这些命名约定作为通用代码开发指南将在整个代码中产生更一致的命名,但您只需要将它们应用于公开暴露的API(公共或受保护的类型和成员以及显式实现的接口)。" - DavidRR
25个回答

53

我喜欢在成员字段前面添加下划线前缀。主要是因为这样,所有的成员字段都会在屏幕顶部的向导栏中按字母顺序显示在我的方法之前。

向导栏


1
那也有助于智能感知。 - Brian
2
我赞成在成员字段前加下划线。这真的很有帮助。 - Sergio Acosta
4
不是一个好主意。下划线前缀可能会被保留。如果我们养成这样的习惯,迟早会遇到强制我们打破约定的冲突。 - kizzx2
2
@cizzx2 在 C# 中,自动实现属性的后备字段使用下划线前缀,因此在私有字段中使用这个前缀会匹配实现。在哪些地方保留下划线前缀? - Seph
6
@Seph,我自己也开始在C#中使用下划线前缀了。忘记那条两年前的评论:P - kizzx2

42

何时应该使用:

  • 当您的项目编码指南要求使用时

何时不应该使用:

  • 当您的项目编码指南规定不使用时

如果您还没有任何指南,您可以选择您或您的团队认为最舒适的任何方式。个人在编写C++代码时倾向于使用 m_ 作为成员变量前缀,这确实有所帮助。但在使用其他语言(尤其是那些没有真正类的语言,如Javascript、Lua)时则不使用。

简而言之,我认为并不存在“正确”或“错误”的方法。


3
他并不是在问什么是对或错的方式,而是询问我们认为什么是正确的方式。 - Ben S
2
正如我所说,正确的方式就是他的方式 ;) - MattJ
7
我觉得我所提出的问题已经很清楚了。这不是关于我何时应该遵循指南的问题。我无法理解为什么人们继续投票支持这个答案。很可能是我没有表达清楚。 - Trap
我们大概都同意以下原则。但是我也回答了没有指南的情况。而且就像我说的,没有对错,这是主观的。我也表达了我的个人偏好。还有什么更多的要求呢? :) - MattJ

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; }

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

显然,在你真正需要显式后备存储时(例如执行验证),这个论点就不适用了。


注意:由于优化的原因,这将导致属性的值在调试器中不容易被看到。 - Ben S
6
这对于自动属性来说是可以的,但是在get/set中有逻辑的属性仍然需要一个支持存储器,因此它并没有回答这个问题。 - mqp
2
那么对于不公开公共属性的私有成员,例如从app.config读取的m_ConnectionString呢? - tsilb
1
啊,我会在本地变量中使用 _name。 - johnc

11

我曾经尝试使用m_、s_、just _以及没有前缀来命名变量。最终我选择了只使用下划线(_)来命名所有的静态和实例变量。我认为将静态变量与实例变量区分开来并不重要。从理论上讲,这听起来很好,但在实践中并不会产生问题。

有一次我的一个同事提出了一种有说服力的观点,即取消所有前缀。我们在一个项目上尝试了一下,效果超出我的预期。于是我把这种方式应用到了下一个项目中,但很快就因为它“干扰”了智能感知而感到烦恼。当你遇到以下情况时:

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

输入“foo”时将会出现实例变量和属性两种建议。在变量前加下划线可以消除烦人的双重建议,所以我又回到了只使用下划线的方式。


11

正如一些人所提到的,微软指南中说:

  

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

我同意这个观点。前缀会让你的代码变得丑陋,并浪费空间来放置无关紧要的字符。尽管如此,通常使用字段作为属性的后备存储,而字段和属性的名称相同(私有字段为驼峰式,属性为帕斯卡式)。在 VB 中,这种情况行不通,因为 VB 不区分大小写。在这种情况下,我建议使用单个 _ 前缀,既不多也不少。在我看来,这样看起来更干净。


3
考虑到.NET Framework中有很多以m_为前缀的私有字段,这实在很有趣。 - Tamas Czinege
我相信你要找的词是反讽,而且是的,.NET BCL充满了违反微软自己建议的情况。:-P - Chris
4
实际上,微软的指南表明内部和私有字段不在这些指南的覆盖范围内(http://msdn.microsoft.com/en-us/library/ms229012.aspx)。 - Sean

10

1
我大部分时间都这样做,但我不喜欢他们希望你如何命名私有成员。他们的方式会与方法参数产生冲突。 - Ed S.
如果我有无法使用自动实现的私有属性,我通常会违反这些准则并在私有字段前加下划线。这是我开始学习Java时养成的老习惯。 - Ben S
2
没有方法参数混淆。C#已经有一种方法将变量标识为类成员,即“this.”前缀。 - Joseph Kingry
1
那就是问题所在。需要消除歧义,因此造成了困惑。 - Ben S
2
没错。当变量名不必相同时,我不喜欢一遍又一遍地输入“this”。 - Ed S.

10

我喜欢在属性的后备字段上打标记(尽管如已提到的,由于自动属性.NET 3.0+减少了这种需要),但不使用“m”作为前缀。首先,这将使它们出现在InteliSense列表的顶部,当我需要使用它们时。

我承认我需要重新查看MSDN的指南,因为这些内容在这些天里变化得如此之快。


10

有了像resharper这样的工具,就没有必要使用前缀。如果您编写短方法,您应该能够很快地确定变量来自哪里。最后,我认为没有必要区分静态还是非静态,因为再次使用resharper将在您尝试执行无法执行的操作时将其标记为红线。即使没有resharper,您也可能会受到编译器的保护。


1
我不知道为什么这个被踩了,这是一个很好的答案。+1 - Randolpho
我仍然更喜欢将成员与局部变量和参数区分开来,前缀非常适合这种情况。(并不是说 -1'd 这个答案 - 但我很想这样做 ;)) - peterchen
@legendlength:我想我只是被宠坏了。Resharper会处理字段的实例化,以及为你处理this.sameNameAsCtorVar。 @peterchen:我猜我们编码方式不同。我喜欢有很多短方法,不需要“_”来告诉我它是什么类型。 - rball
1
你真是个被宠坏了的孩子。我们买不起Resharper :( (希望有一个更便宜且同样好用的替代品)。 - LegendLength
我换了工作,现在在公司没有Resharper,只有在家里才有。这就像是单手编码一样。很奇怪,因为从我的角度来看,你不能不拥有像Resharper这样的工具。它节省的时间随着使用时间的增长呈指数级增长。不过,我认为没有这个前缀唯一的问题就是ScottS提到的智能感知问题。 - rball
显示剩余2条评论

6

我总是在成员变量前加上m_,在静态变量前加上s_,原因与你所说的相同。有些人用下划线作为成员变量的前缀,但我一直觉得这看起来有点奇怪(但这只是个人偏好)。

我和大多数合作的人都使用m_/s_前缀。我认为重要的是保持一致,不管你使用什么。


啊,这就是那个奇怪的惯例的由来... ^^ 我一直以为那是 VB 的东西(因为 _ 被用作换行转义字符)。 - Christian Klauser
1
此外,我在函数参数中使用下划线(_)。 - CW Holeman II

5

我从不使用它们。这会鼓励粗心编码。 MSDN编码指南才是王道。


4
为什么?这应该如何鼓励懒散的编码? - marc_s
因为它允许您在字段、局部变量或参数中使用相同的名称。这是保持命名清晰的好方法。 - Inferis
9
在构造函数参数中将参数命名为“name”,并将用于保存该值的字段命名为“_name”存在不规范之处。 - Sergio Acosta
1
@SergioAcosta 这种行为并不是懒散的表现。仅仅为了区分成员变量而凭空想出另一个参数名称是愚蠢的。这种行为可能会导致更冗长、难以理解的代码。 - 0b101010

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接