命名约定 - 在C++和C#变量中使用下划线

Sta*_*tan 131 c# c++ naming-conventions

_var在类字段中看到变量名是很常见的.下划线是什么意思?是否有所有这些特殊命名约定的参考?

jdm*_*hal 110

下划线只是一个惯例; 而已.因此,它的使用总是与每个人有所不同.以下是我对这两种语言的理解:

在C++中,下划线通常表示私有成员变量.

在C#中,我通常看到它仅在为公共属性定义底层私有成员变量时使用.其他私有成员变量没有下划线.尽管如此,随着自动属性的出现,这种用法已基本消失.

之前:

private string _name;
public string Name
{
    get { return this._name; }
    set { this._name = value; }
}
Run Code Online (Sandbox Code Playgroud)

后:

public string Name { get; set; }
Run Code Online (Sandbox Code Playgroud)

  • 除了希望其属性不可变的团队. (11认同)
  • @Thomas Matthews - 不在C#中. (11认同)
  • @ChaosPandion我假设"immutable"的意思实际上是"只读",在这种情况下,可以使用`public string Name {get; 私人集; }`.没错,它不是完全不可改变的,但它就在那里. (11认同)
  • 以下划线开头的标识符保留给编译器.使用前缀下划线**可能与编译器符号冲突. (9认同)
  • @Thomas在类上下文中,标识符以下划线*开头,后跟大写字母*a在C++中保留.`_var`不是保留的. (5认同)
  • @Matteo 您对“*明确禁止*”的使用过于强烈。您引用的是 Microsoft 发布的文体指南,而不是语言或编译器参考。不同的组织会有不同的风格。 (2认同)

Con*_*nos 69

请不要在C++中的任何变量名称或参数名称之前使用UNDERSCORES!

对于C++实现者,保留以下划线或双下划线开头的名称.带有下划线的名称保留供库使用.

如果您已阅读C++编码标准,您将在第一页中看到它:

"不要过度分割命名,但要使用一致的命名约定:只有两个必须符合:a)永远不要使用"卑鄙的名字",以下划线开头或含有双下划线的名称;" (p2,C++编码标准,Herb Sutter和Andrei Alexandrescu)

此外,您可以自己看到为什么在开发软件时使用下划线会造成灾难性后果.

尝试编译一个简单的helloWorld.cpp程序,如下所示:

g++ -E helloWorld.cpp
Run Code Online (Sandbox Code Playgroud)

你会看到后台发生的一切.这是一个片段:

   ios_base::iostate __err = ios_base::iostate(ios_base::goodbit);
   try
     {
       __streambuf_type* __sb = this->rdbuf();
       if (__sb)
  {
    if (__sb->pubsync() == -1)
      __err |= ios_base::badbit;
    else
      __ret = 0;
  }
Run Code Online (Sandbox Code Playgroud)

你可以看到有多少名字以双下划线开头!

此外,如果查看虚拟成员函数,您将看到*_vptr是为虚拟表生成的指针,当您在类中使用一个或多个虚拟成员函数时,该指针会自动生成!但那是另一个故事......

如果你使用下划线,你可能会遇到冲突问题,你将不会有任何想法导致它,直到它为时已晚.

  • 我理解有些人不想使用下划线和小写字母,因为他们可能无法明确什么是合法的.即使某些作者建议不使用它,C++标准也允许它.对我来说,既然它是完全合法的而不是保留的,我认为没有任何理由认为它有风险.感谢您的反馈意见. (7认同)
  • 不是全局或文件范围的名称,并以下划线和小写字母开头是完全正常的吗?我一直这样做,因为它对于特定情况非常干净,例如:void A :: set_size(int _size){size = _size; }.对于像这样的琐碎用途,你会怎么做? (3认同)
  • 我认为,在非全局/文件范围内允许使用下划线字母和下划线字母.你能告诉我它在标准中说的不是吗?尾随下划线的问题是我有时会将其用于成员变量.所以我可能有函数'int size();' member var'int size_;' 和参数'int _size'.这往往很好地涵盖了事情,我没有看到更好的选择.与STL一起使用的泛型不可能使用大写的函数.C#人喜欢的'this.size'风格似乎容易出错,除非你总是用它来进行丑陋的会员访问. (3认同)
  • @tukra:这不是**完全**合法的。C++ 标准 **only** 允许您在局部范围内使用单个下划线后跟小写字母。祝你好运!:-) (3认同)
  • @tukra 使用 `_config` 的问题是它很容易意外执行 `_XMLconfig`,这可能与实现宏(大写缩写)冲突。请记住,初级维护程序员可能至少有 50% 的机会不知道 `_XMLconfig` 不好,因此当他们看到 `_config` 很好时,他们会认为 `_XMLconfig` 很好。 (3认同)
  • 抱歉.我以为我们过去需要重复这些资格.在文件范围以外的每个范围内都允许以下划线后跟小写字母开头的C++标识符.它在函数,函数原型,类,结构,联合,枚举以及放在命名空间中的所有内容都是安全合法的.如果您遵循将所有代码放在命名空间中的常见做法,那么您就完全安全了. (2认同)
  • @GabrielStaples 来自工作草案,文档编号 N4296,第 2.10 章 - 标识符:“此外,某些标识符保留供 C++ 实现使用,不得用于其他用途;不需要诊断。**(a)**每个包含双下划线 __ 或以下划线开头后跟大写字母的标识符都保留给实现以供任何使用。**(b)** 每个以下划线开头的标识符都保留给实现用作全局命名空间中的名称。”。希望这可以帮助。:-) (2认同)
  • @ConstantinosGlynos 您引用的标准表示这些标识符是“在全局命名空间中”保留的。在类或函数的范围内使用以下划线开头的标识符,后跟小写字母是完全合法且广泛常见的做法。 (2认同)

Zie*_*ied 43

实际上,_var惯例来自VB而不是C#或C++(m _,......是另一回事).

这是为了克服VB在声明Proprieties时不区分大小写的情况

例如,这样的代码在VB中是不可能的,因为它考虑userUser作为相同的标识符

Private user As String

Public Property User As String
  Get
    Return user
  End Get
  Set(ByVal Value As String)
    user = value
  End Set
End Property
Run Code Online (Sandbox Code Playgroud)

所以为了克服这个问题,一些人使用了一个约定来将'_'添加到私有字段中

Private _user As String

Public Property User As String
  Get
    Return _user
  End Get
  Set(ByVal Value As String)
    _user = value
  End Set
End Property
Run Code Online (Sandbox Code Playgroud)

由于许多约定适用于.Net并且在C#和VB.NET约定之间保持一致,因此它们使用相同的约定.

我找到了我所说的参考文献:http:/ 10/ 10rem.net/articles/net-naming-conventions-and-programming-standards---best-practices

骆驼案与领先的下划线.在VB.NET中,始终指示"受保护"或"私有",不要使用"暗淡".不鼓励使用"m_",因为使用的变量名称与属性的区别仅在于大小写,特别是受保护的变量违反了合规性,如果你在VB.NET中编程,会让你的生活变得痛苦,因为你必须为您的成员命名与accessor/mutator属性不同的东西.在这里的所有项目中,领先的下划线确实是唯一有争议的.对于我的私有变量,我个人更喜欢使用直接下划线的驼峰情况,因此我不必使用"this"来限定变量名称.区分构造函数或其他可能发生命名冲突的参数.由于VB.NET的大小写不敏感,这更为重要,因为除了下划线之外,访问者属性通常与私有成员变量具有相同的名称.至于m_,它实际上只是关于美学.我(以及其他许多人)发现丑陋,因为看起来变量名中有一个洞.这几乎令人反感.我曾经一直在VB6中使用它,但这只是因为变量没有前导下划线.看到它消失,我感到高兴.Microsoft建议不要使用m_(和直_),即使他们在代码中都这样做了.此外,直接用"m"作为前缀.当然,由于它们主要在C#中编码,因此它们可以具有仅在属性方面不同的私有成员.VB人们必须做点别的事情.我建议使用支持它的所有语言的前导下划线,而不是尝试逐个语言的特殊情况.如果我希望我的类完全符合CLS,我可以在任何C#protected成员变量上留下前缀.然而,在实践中,我从不担心这一点,因为我将所有可能受保护的成员变量保密,并提供受保护的访问器和变更器.原因:简而言之,此约定很简单(一个字符),易于阅读(您的眼睛不会被其他主要字符分心),并成功避免命名与过程级别变量和类级别属性的冲突.类级别属性.我推荐所有支持它的语言的前导下划线.如果我希望我的类完全符合CLS,我可以在任何C#protected成员变量上留下前缀.然而,在实践中,我从不担心这一点,因为我将所有可能受保护的成员变量保密,并提供受保护的访问器和变更器.原因:简而言之,此约定很简单(一个字符),易于阅读(您的眼睛不会被其他主要字符分心),并成功避免命名与过程级别变量和类级别属性的冲突.类级别属性.我推荐所有支持它的语言的前导下划线.如果我希望我的类完全符合CLS,我可以在任何C#protected成员变量上留下前缀.然而,在实践中,我从不担心这一点,因为我将所有可能受保护的成员变量保密,并提供受保护的访问器和变更器.原因:简而言之,此约定很简单(一个字符),易于阅读(您的眼睛不会被其他主要字符分心),并成功避免命名与过程级别变量和类级别属性的冲突.类级别属性.我从不担心这一点,因为我将所有可能受保护的成员变量保密,并提供受保护的访问器和变更器.原因:简而言之,此约定很简单(一个字符),易于阅读(您的眼睛不会被其他主要字符分心),并成功避免命名与过程级别变量和类级别属性的冲突.类级别属性.我从不担心这一点,因为我将所有可能受保护的成员变量保密,并提供受保护的访问器和变更器.原因:简而言之,此约定很简单(一个字符),易于阅读(您的眼睛不会被其他主要字符分心),并成功避免命名与过程级别变量和类级别属性的冲突.类级别属性.


bsr*_*uth 5

第一位评论者(R Samuel Klatchko)引用了:在C++标识符中使用下划线有哪些规则?它回答了关于C++中下划线的问题.通常,您不应该使用前导下划线,因为它是为编译器的实现者保留的.您看到的代码_var可能是遗留代码,也可能是由使用旧命名系统长大的人编写的代码,该系统在前导下划线上没有皱眉.

正如其他答案所述,它曾经在C++中用于识别类成员变量.但是,就装饰器或语法而言,它没有特殊含义.所以如果你想使用它,它将编译.

我会把C#讨论留给别人.


5ou*_*und 5

_var没有意义,仅用于简化变量是私有成员变量的目的。

在C ++中,使用_var约定是不好的形式,因为在标识符前面有一些规则来控制下划线的使用。_var保留为全局标识符,而_Var(下划线+大写字母)随时保留。这就是为什么在C ++中,您会看到人们使用var_约定的原因。