32

毫无疑问,对于理解代码来说,给成员变量一个前缀是很重要的,这样它们就可以很容易地与“正常”变量区分开来。

但是你使用什么样的前缀?

我一直在处理我们使用m_作为前缀的项目,在其他项目中我们只使用下划线(我个人不喜欢,因为只使用下划线不够说明)。

在另一个项目中,我们使用了长前缀形式,它也包括变量类型。例如mul_是u nsigned long类型的成员变量的前缀。

现在让我知道您使用哪种前缀(并请说明原因)。

编辑:你们中的大多数人似乎在没有为成员变量添加特殊前缀的情况下编写代码!这取决于语言吗?根据我的经验,C++ 代码倾向于使用下划线或m_作为成员变量的前缀。其他语言呢?

4

33 回答 33

55

毫无疑问,对于理解代码来说,给成员变量一个前缀是很重要的,这样它们就可以很容易地与“正常”变量区分开来。

我对这一说法提出异议。如果您的语法高亮显示得当,那一点也没有必要。一个好的 IDE 可以让您以可读的英文编写代码,并可以通过其他方式向您显示符号的类型和范围。当插入点位于其中一个符号上时,Eclipse 通过突出显示声明和符号的使用做得很好。

编辑,谢谢 slim:像 Eclipse 这样的优秀语法高亮工具还可以让您使用粗体或斜体文本,或者完全更改字体。例如,我喜欢静态事物的斜体。

另一个编辑:这样想;变量的类型和范围是次要信息。它应该可用且易于查找,但不要对您大喊大叫。如果您使用前缀 likem_或类型 like LPCSTR,当您只想阅读主要信息(代码的意图)时,就会变成噪音。

第三次编辑:无论语言如何,这都适用。

于 2008-09-21T18:25:28.987 回答
46

我根本不使用任何前缀。如果我遇到将局部变量或方法参数与类成员混淆的危险,那么方法或类都太长了,并且从拆分中受益

这(可以说)不仅使代码更具可读性和“流利”,而且最重要的是鼓励结构良好的类和方法。最后,它因此归结为与前缀或无前缀困境完全不同的问题。

更新:好吧,品味和偏好会改变,不是吗.. 我现在使用下划线作为成员变量的前缀,因为从长远来看,它已被证明有利于识别局部变量和成员变量。尤其是新的团队成员,当两者不容易被识别时,有时会遇到困难。

于 2008-09-21T18:24:33.060 回答
42

没有任何。我曾经使用下划线,但是在其他人不喜欢它并且没有错过它的项目中被淘汰了。一个像样的 IDE 或一个像样的内存会告诉你什么是成员变量,什么不是。我们项目的一位开发人员坚持要放“这个”。在每个成员变量前面,当我们处理名义上是“他的”的代码区域时,我们会取笑他。

于 2008-09-21T18:24:10.517 回答
22

仅下划线。

就我而言,我之所以使用它,是因为这就是我工作场所的编码标准文档所说的。但是,我看不出在变量开头添加 m_ 或一些可怕的匈牙利语的意义。极简主义的“仅下划线”使其易于阅读。

于 2008-09-21T18:21:02.727 回答
20

保持一致比什么都重要,所以选择你和你的队友都同意的东西并坚持下去。如果你编码的语言有一个约定,你应该尽量遵守它。没有什么比不一致地遵循前缀规则的代码库更令人困惑的了。

对于 c++,除了 _ 有时会作为编译器关键字的前缀之外,还有另一个原因更喜欢 m_ 而不是 _。m 代表成员变量。这也使您能够在局部变量和其他变量类之间消除歧义,s_ 表示静态变量,g_ 表示全局变量(但当然不要使用全局变量)。

至于 IDE 将始终照顾您的评论,IDE 真的是您查看代码的唯一方式吗?您的差异工具是否具有与您的 IDE 相同的语法高亮质量水平?你的源代码控制修订历史工具呢?您甚至从未将源文件添加到命令行吗?现代 IDE 是出色的效率工具,但无论您在何种上下文中阅读代码,都应该易于阅读。

于 2008-09-21T19:24:17.487 回答
12

我更喜欢使用this关键字。这意味着this.datathis->data代替一些依赖于社区的命名。

因为:

  • 现在的 IDE 键入this.弹出窗口 intellinsense
  • 在不知道定义命名的情况下,这对每个人来说都是显而易见的

顺便说一句,用字母作为变量前缀来表示它们的类型在好的 IDE 中已经过时了,这让我想起了Joel 的这篇文章

于 2008-09-21T18:32:15.677 回答
7

我们使用 m_ ,然后使用稍微修改的 Simonyi 符号,就像 Rob 在之前的回复中所说的那样。因此,前缀似乎很有用,而且 m_ 不太麻烦且易于搜索。

为什么要记谱法?为什么不遵循(对于 .NET)依赖于名称大小写的 Microsoft 表示法建议?

先说后一个问题:正如所指出的,VB.NET 对大小写漠不关心。数据库和(尤其是)DBA 也是如此。当我必须保持直接的 customerID 和 CustomerID(例如,在 C# 中)时,这让我很头疼。因此,大小写是一种表示法,但不是一种非常有效的表示法。

前缀表示法在几个方面具有价值:

  1. 在不使用 IDE 的情况下增加人类对代码的理解。就像在代码审查中一样——我仍然发现最初在纸上最容易做到这一点。
  2. 曾经编写过 T-SQL 或其他 RDBMS 存储过程吗?在数据库列名上使用前缀符号真的很有帮助,特别是对于我们这些喜欢使用文本编辑器来处理这类东西的人。

简而言之,前缀作为一种符号形式很有用,因为仍然存在智能 IDE 不可用的开发环境。将 IDE(一种软件工具)视为允许我们使用一些快捷方式(如智能输入),但不包含整个开发环境。

IDE 是一个集成开发环境,就像汽车是一个交通网络一样:只是更大系统的一部分。我不想遵循“汽车”惯例,比如呆在有标记的道路上,有时,步行穿过一块空地会更快。依靠 IDE 来跟踪变量类型就像需要汽车的 GPS 来穿过空地一样。以可移植的形式拥有知识(虽然可能很尴尬,但可能会有“m_intCustomerID”),而不是每次小的变化都跑回车上。

也就是说,m_ 约定或“this”约定都是可读的。我们喜欢 m_ 因为它很容易被搜索并且仍然允许变量类型跟随它。同意太多其他框架代码活动使用简单的下划线。

于 2008-09-21T20:05:45.267 回答
6

使用 C#,我已经从 'm_' 前缀移动到只是一个下划线,因为 'm_' 是C++ 的遗产

微软官方指南告诉你不要使用任何前缀,并且在私有成员上使用骆驼大小写,在公共成员上使用帕斯卡大小写。问题是这与来自同一来源的另一条准则相冲突,该准则指出您应该使所有代码与 .NET 中使用的所有语言兼容。例如,VB.NET 在大小写之间没有区别。

所以对我来说只是一个下划线。这也使得通过 IntelliSense 访问变得容易,并且只调用公共成员的外部代码不必看到视觉上凌乱的下划线。

更新:我不认为C# “this.”-prefix对“Me”有帮助。在 VB 中,仍然会看到“Me.age”与“Me.Age”相同。

于 2008-09-21T18:42:06.200 回答
5

这取决于我使用的是哪个框架!如果我正在编写 MFC 代码,那么我使用m_和匈牙利符号。对于其他东西(往往是 STL/Boost),我会在所有成员变量中添加一个下划线后缀,并且我不会使用匈牙利符号。

MFC类

class CFoo  
{  
private:  
    int m_nAge;  
    CString m_strAddress;  
public:  
    int GetAge() const { return m_nAge; }  
    void SetAge(int n) { m_nAge = n; }  
    CString GetAddress() const { return m_strAddress;  
    void SetAddress(LPCTSTR lpsz) { m_strAddress = lpsz; }  
};

STL 类

class foo  
{  
private:  
    int age_;  
    std::string address_;  
public:  
    int age() const { return age_; }  
    void age(int a) { age_ = a; }  
    std::string address() const { return address_; }  
    void address(const std::string& str) { address_ = str; }  
};

现在这可能看起来有点奇怪 - 两种不同的风格 - 但它适用于我,并且编写大量不使用与 MFC 本身相同的风格的 MFC 代码看起来很难看。

于 2008-09-21T18:35:00.320 回答
4

我在成员变量前面加上“m”,在参数(在函数中)加上“p”。所以代码看起来像:

class SomeClass {
    private int mCount;
    ...
    private void SomeFunction(string pVarName) {...}
}

我发现这很快就能告诉你任何变量的基本范围——如果没有前缀,那么它就是本地变量。此外,在读取函数时,您无需考虑传入的内容和局部变量。

于 2008-09-21T19:41:44.810 回答
3

这真的取决于语言。我是一个 C++ 人,用下划线作为前缀有点棘手。在某些情况下(取决于范围),该语言保留以下划线开头的内容用于实现。双下划线或大写字母后的下划线也有特殊处理。所以我说只是避免这种混乱并简单地选择其他前缀。'm' 没问题 IMO。'm_' 有点多,但也不可怕。真的是口味问题。

但要注意那些 _leadingUnderscores。你会惊讶于有多少编译器和库内部被如此命名,如果你不是非常小心的话,肯定会有意外和混淆的空间。拒绝吧。

于 2008-09-21T18:26:38.327 回答
3

大多数时候,我使用python。Python 要求您使用 self.foo 来访问当前类实例的属性 foo。这样就解决了您所处理的实例的局部变量、参数和属性混淆的问题。
一般来说,我喜欢这种方法,即使我不喜欢被迫这样做。因此,我理想的做法是不这样做,而是在 this 或 self 上使用某种形式的属性访问以获取成员变量。这样,我不必将名称与元数据混淆。

于 2008-09-21T19:21:46.543 回答
3

我是个怪人,我在成员变量前面加上类名的首字母(骆驼大小写)。

TGpHttpRequest = class(TOmniWorker)
strict private
  hrHttpClient  : THttpCli;
  hrPageContents: string;
  hrPassword    : string;
  hrPostData    : string;

大多数 Delphi 人只使用 F。

TGpHttpRequest = class(TOmniWorker)
strict private
  FHttpClient  : THttpCli;
  FPageContents: string;
  FPassword    : string;
  FPostData    : string;
于 2008-09-21T20:22:36.223 回答
3

如果语言支持thisMe关键字,则不使用前缀,而是使用所述关键字。

于 2008-09-22T21:25:04.677 回答
2

另一个技巧是命名约定

所有成员变量都像往常一样命名,没有任何前缀(或“this.”是不是在项目中通常这样做)

但是它们很容易与局部变量区分开来,因为在我的项目中,这些局部变量总是被命名为:

  • aSomething:代表一个对象。
  • some ManyThings:对象列表。
  • AState 或SomeThing: 用于布尔状态。

任何不以“a”、“some”或“is/has”开头的变量都是成员变量。

于 2008-09-21T18:57:31.327 回答
2

由于 VB.NET 不区分大小写,因此我在成员变量前面加上下划线并在名称的其余部分加上驼峰式大小写。我将属性名称大写。

Dim _valueName As Integer

Public Property ValueName() As Integer
于 2008-09-21T19:02:11.270 回答
2

我和不使用前缀的人在一起。

IDE 现在非常好,从语法着色、鼠标悬停工具提示和轻松导航到其定义,一眼就能轻松找到有关变量的信息。

这是您可以从变量的上下文和命名约定(例如局部变量和私有字段的 lowerCamelCase,属性和方法等的 UpperCamelCase 等)以及布尔值的“hasXXXX”和“isXX”等内容中获得的最重要的内容。

多年来我没有使用前缀,但我确实曾经是“this”。前缀怪物,但除非绝对必要,否则我已经取消了(谢谢,Resharper)。

于 2008-09-21T20:19:46.870 回答
2

一个_仅用作视觉指示器。(C#)

  • 有助于使用智能感知对成员进行分组。
  • 阅读代码时更容易发现成员变量。
  • 更难隐藏具有本地定义的成员变量。
于 2008-09-21T20:58:02.287 回答
2

_代替this.

我使用_too 而不是this.因为它更短(少4 个字符),它是成员变量的一个很好的指标。此外,使用此前缀可以避免命名冲突。例子:

public class Person {
  private String _name;

  public Person(String name) {
    _name = name;
  }
}

将其与此进行比较:

public class Person {
  private String name;

  public Person(String name) {
    this.name = name;
  }
}

我发现第一个例子更短更清晰。

于 2010-12-11T12:15:38.667 回答
1

这有点取决于您使用的语言。

在 C# 中,您可以使用“this”前缀引用任何成员,例如“this.val”,这意味着不需要前缀。VB 具有与“我”类似的功能。

在有用于指示成员访问的内置符号的语言中,我看不到使用前缀的意义。在其他语言中,我想使用该语言普遍接受的约定是有意义的。

请注意,使用内置表示法的好处之一是您也可以在访问类的属性和方法时使用它,而不会影响您的命名约定(这在访问非私有成员时尤其重要)。使用任何类型的指标的主要原因是作为一个标志,表明您在类中可能造成副作用,因此在使用其他成员时最好使用它,无论它们是否是字段/属性/方法/等.

于 2008-09-21T18:26:16.190 回答
1

我在这里使用驼峰式大小写和下划线。我使用下划线是因为我使用 C#,而且我已经习惯在构造函数中避免使用“this”关键字。我是骆驼案例方法范围的变体,所以下划线提醒我当时正在使用什么范围。否则,只要您不尝试添加代码中已经很明显的不必要信息,我认为这并不重要。

于 2008-09-21T19:06:24.830 回答
1

我曾经在 C++ 中使用 m_ perfix,但在 C# 中,我更喜欢将驼峰大小写用于字段,将帕斯卡大小写用于其属性。

private int fooBar;
public int FooBar
{
  get { return fooBar; }
  set { fooBar = value; }
}
于 2008-09-21T20:18:31.727 回答
1

我喜欢 m_ 但只要在代码库中使用约定,我就很喜欢它。

于 2009-06-05T00:27:44.703 回答
0

您的 mul_ 示例正朝着 Charles Simonyi 的 Apps Hungarian 表示法前进。

我更喜欢保持简单,这就是为什么我喜欢使用 m_ 作为前缀。

这样做可以更容易地查看您必须去哪里查看原始声明。

于 2008-09-21T18:22:37.837 回答
0

我倾向于在 C++ 中使用 m_,但不介意在 Java 或 C# 中使用它。这取决于编码标准。对于混合了下划线和 m_ 的遗留代码,我会将代码重构为一个标准(给定合理的代码大小)

于 2008-09-21T18:35:04.470 回答
0

我用 @。

:D j/k - 但是否确实取决于语言。如果它有 getter/setter,我通常会在私有成员变量前面放一个 _,并且 getter/setter 将具有相同的名称而没有 _。否则,我通常不使用任何。

于 2008-09-21T18:43:44.730 回答
0

对于我自己的项目,我使用 _ 作为后缀(正如上面提到的 Martin York,作为前缀是 C/C++ 编译器实现标准的保留),并且我在处理Symbian 项目时。

于 2008-09-21T19:25:05.707 回答
0

在 Java 中,一种常见的约定是在成员变量前面加上“my”和 UseCamelCaseForTheRestOfTheVariableName。

于 2008-09-21T20:09:42.573 回答
-1

如果没有必要,则无,否则单下划线。适用于蟒蛇。

于 2008-09-21T18:24:23.077 回答
-1

如果确实需要为成员变量添加前缀,我肯定更喜欢m_只使用下划线。我发现下划线本身会降低可读性,并且可能与 C++ 保留字混淆。

但是,我确实怀疑成员变量是否需要任何特殊符号。即使忽略 IDE 的帮助,也不明白为什么会混淆什么是本地变量和什么是成员变量。

于 2008-09-21T18:53:13.677 回答
-1

没有前缀。而且,对于纯功能/基于堆栈的无变量名。但是,如果我真的必须使用副作用,如果我想输出任何东西,我可能会使用p->其中 p 是传递给我的函数的参数的外部指针。

我认为使用前缀/前缀会很愚蠢。

__EXTERN_GLOBAL_hungariannotationvariabletypeVendorName-my_member_prefix-Category-VariableName

仔细考虑 mul 示例,我的成员变量是一个无符号长整数,表示乘法指令的操作码可能是 mulmul。

于 2008-09-21T20:27:09.630 回答
-1

Symbian 使用“i”作为成员的前缀,使用“a”作为参数。

于 2008-09-22T10:50:46.543 回答
-1

我只使用 _后缀(前缀 _ 在 c/c++ 中保留,正如上面许多人所指出的那样)。我喜欢它主要是因为我讨厌像“aCircle”这样的参数名称,除非绝对必要,否则我也不喜欢写出 this.circle。(我只对公共访问成员变量这样做,'因为这些我不使用下划线后缀)。

于 2008-09-22T11:09:19.010 回答