【问题标题】:Naming convention - underscore in C++ and C# variables命名约定 - C++ 和 C# 变量中的下划线
【发布时间】:2011-03-09 08:57:17
【问题描述】:

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

【问题讨论】:

  • 我不同意 - 这不是完全重复。这两个问题都与变量名称中的下划线有关,但在实际内容中是完全不同的问题。 (一方面,这个是关于 C# 的)
  • 一些被误导的公司编码指南建议在成员变量中添加疣以将它们与局部变量区分开来,因为他们认为类和函数将不可避免地变得臃肿,以至于你无法跟踪没有什么是什么像这样的模糊线索。提出这种约定的人往往是代码最需要它们的人。
  • @Mike - 你的笼统陈述是不正确的。我发现使用这种约定可以更轻松地快速扫描方法并更好地理解类。
  • 在 C++ 中,避免使用 前导 下划线。在许多情况下(即在全局范围内,当一个大写字母跟随等)它们被保留用于实现,并且您实际上冒着被一些宏践踏的风险。因此,如果您想要它们,请将它们设为 尾随下划线

标签: c# c++ naming-conventions


【解决方案1】:

它只是意味着它是类中的成员字段。

【讨论】:

    【解决方案2】:

    没有特定的单一命名约定,但我已经看到私有成员的命名约定。

    【讨论】:

      【解决方案3】:

      Microsoft 的 C# 命名标准规定变量和参数应使用小写驼峰形式 IE: paramName。该标准还要求字段遵循相同的形式,但这可能导致代码不清晰,因此许多团队要求使用下划线前缀来提高清晰度IE:_fieldName

      【讨论】:

        【解决方案4】:

        下划线只是一个约定;而已。因此,它的使用对每个人来说总是有些不同。以下是我对所讨论的两种语言的理解:

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

        在 C# 中,我通常看到它仅在为公共属性定义底层私有成员变量时使用。其他私有成员变量不会有下划线。但是,随着自动属性的出现,这种用法在很大程度上已经被淘汰了。

        之前:

        private string _name;
        public string Name
        {
            get { return this._name; }
            set { this._name = value; }
        }
        

        之后:

        public string Name { get; set; }
        

        【讨论】:

        • 希望其属性不可变的团队除外。
        • 以下划线开头的标识符是为编译器保留的。使用前缀下划线可能与编译器符号冲突。
        • @Thomas Matthews - 不在 C# 中。
        • @ChaosPandion 我假设您所说的“不可变”实际上是“只读”,在这种情况下可以使用public string Name { get; private set; }。诚然,它不是完全不可变的,但它就在那里。
        • @Thomas 在类上下文中,以下划线开头的标识符后跟大写字母在 C++ 中保留。 _var 未保留。
        【解决方案5】:

        根据我的经验(当然有限),下划线表示它是私有成员变量。不过,正如咕噜所说,这将取决于团队。

        【讨论】:

          【解决方案6】:

          我使用 _var 命名我的类的成员变量。我这样做的主要原因有两个:

          1) 它可以帮助我在以后阅读代码时跟踪类变量和局部函数变量。

          2) 当我在寻找类变量时,它有助于 Intellisense(或其他代码完成系统)。只知道第一个字符有助于过滤可用变量和方法的列表。

          【讨论】:

          • 在更大的方法中依靠悬停智能感知或扫描来查看变量是否在本地定义是一件麻烦事。出于与您提到的相同原因,也更喜欢“__”作为静态变量,但它目前不受欢迎。
          • 静态的双下划线看起来很不错,但即使在命名空间内也会保留。
          【解决方案7】:

          许多人喜欢在私有字段前加上下划线。这只是一个命名约定。

          C# 的“官方”命名约定为私有字段规定了简单的小写名称(无下划线)。

          我不知道 C++ 的标准约定,尽管下划线被广泛使用。

          【讨论】:

            【解决方案8】:

            当您阅读代码,尤其是不属于您自己的代码时,这样的命名约定非常有用。强大的命名约定有助于指示特定成员的定义位置、成员类型等。大多数开发团队采用简单的命名约定,并简单地在成员字段前加上下划线 (_fieldName)。过去,我对 C# 使用了以下命名约定(这是基于 Microsoft 对 .NET 框架代码的约定,可以通过 Reflector 看到):

            实例字段: m_fieldName
            静态字段: s_fieldName
            公共/受保护/内部成员: PascalCasedName()
            私人会员: camelCasedName()

            这有助于人们在快速阅读不熟悉的代码时了解成员的结构、用途、可访问性和位置。

            【讨论】:

            • 其实微软不推荐使用m_、s_前缀。 不要为字段名使用前缀。例如,不要使用 g_ 或 s_ 来区分静态字段和非静态字段。 msdn.microsoft.com/en-us/library/ms229012.aspx
            • 就像我说的,用 Reflector 看看他们的源代码。你会惊讶他们有多少回避自己的建议。 ;) 正如我的帖子所提到的,它有助于提高代码的可读性,而且我的上一个团队非常喜欢上面列出的命名约定。
            【解决方案9】:

            这只是一些程序员在操作类的成员或其他类型的变量(参数、函数的局部变量等)时使用的约定。另一个也广泛用于成员变量的约定是在名称前加上“m_”。

            无论如何,这些只是约定,您不会找到所有它们的单一来源。它们是风格问题,每个编程团队、项目或公司都有自己的(甚至没有)。

            【讨论】:

              【解决方案10】:

              对于 C#,Microsoft Framework Design Guidelines 建议不要为 public 成员使用下划线字符。对于私人成员,可以使用下划线。事实上,Jeffrey Richter(经常在指南中引用)例如使用 m_ 和私有静态成员的“s_”。

              就我个人而言,我只使用 _ 来标记我的私人成员。 “m_”和“s_”接近匈牙利符号,这不仅在 .NET 中不受欢迎,而且可能非常冗长,而且我发现有很多成员的类很难按字母顺序进行快速眼睛扫描(想象 10 个变量都以 m_ 开头) .

              【讨论】:

              • 由于匈牙利符号表示类型,我不认为你真的可以说 m/s 接近它。
              • @JerryNixon-MSFT 在谈到匈牙利概念时,我们是否将可变数据类型和可变可见性类型识别为同一事物?
              • 所以你不区分静态成员和实例成员只有_,或者?
              【解决方案11】:

              实际上_var 约定来自 VB 而不是 C# 或 C++(m_,... 是另一回事)。

              这是为了克服 VB 在声明属性时不区分大小写的问题。

              例如,这样的代码在 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
              

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

              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
              

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

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

              带有前导下划线的驼峰式大小写。在 VB.NET,始终指示“受保护”或 “私人”,不要使用“暗淡”。用于 不鼓励使用“m_”,使用 a 变量名不同于 唯一情况下的财产,尤其是 受保护的变量,因为这违反了 合规性,并将使您的生活 如果你在 VB.NET 中编程会很痛苦,因为你 必须命名你的成员 不同于 访问器/修改器属性。在所有 这里的项目,前导下划线 真的是唯一有争议的。 我个人更喜欢直接 我的无下划线骆驼案 私有变量,这样我就没有 用“this”限定变量名。 区别于参数 构造函数或我在其他地方 可能会发生命名冲突。 由于 VB.NET 不区分大小写,这 更重要的是你的 访问器属性通常有 与您的私人会员同名 除下划线外的变量。 就 m_ 而言,它真的只是 关于美学。我(和许多其他人) 发现 m_ 丑陋,因为它看起来像那里 是变量名中的一个洞。它是 几乎令人反感。我曾经在 VB6 一直都在,但那只是 因为变量不能有 前导下划线。我不可能 更高兴看到它消失。微软 建议反对 m_ (和 直_)即使他们都做了 在他们的代码中。另外,前缀 直接的“m”就出来了。当然, 因为他们主要用 C# 编写代码,所以他们可以 有仅不同的私人成员 如果从属性。 VB伙计们 必须做其他事情。而不是 试着想出 语言的特殊情况,我 推荐前导下划线为 所有支持它的语言。如果 我希望我的课完全 符合 CLS,我可以省略 任何 C# 受保护成员的前缀 变量。然而在实践中,我 永远不要担心这个,因为我保留了所有 潜在受保护的成员变量 私有,供应保护 取而代之的是访问器和突变器。为什么: 简而言之,这个约定是 简单(一个字符),易于阅读 (你的眼睛不会被其他人分心 主角),并成功 避免命名冲突 过程级变量和 类级属性。类级属性。

              【讨论】:

                【解决方案12】:

                您可以创建自己的编码指南。只需为团队的其他成员编写清晰的文档即可。

                使用 _field 有助于 Intelilsense 过滤所有类变量,只需键入 _。

                我一般都跟着Brad Adams Guidelines,但建议不要使用下划线。

                【讨论】:

                  【解决方案13】:

                  第一个评论者(R Samuel Klatchko)引用了:What are the rules about using an underscore in a C++ identifier?,它回答了关于 C++ 中下划线的问题。通常,您不应该使用前导下划线,因为它是为编译器的实现者保留的。您使用_var 看到的代码可能是遗留代码,或者是由使用旧命名系统长大的人编写的代码,该命名系统不会对前导下划线皱眉。

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

                  我会把 C# 的讨论留给其他人。

                  【讨论】:

                    【解决方案14】:

                    There is a fully legit reason to use it in C#: 如果代码也必须可以从 VB.NET 扩展。 (否则,我不会。)

                    由于 VB.NET 不区分大小写,因此没有简单的方法可以访问此代码中受保护的 field 成员:

                    public class CSharpClass
                    {
                        protected int field;
                        public int Field { get { return field; } }
                    }
                    

                    例如这将访问属性 getter,而不是字段:

                    Public Class VBClass
                        Inherits CSharpClass
                    
                        Function Test() As Integer
                            Return Field
                        End Function
                    
                    End Class
                    

                    哎呀,我什至不能用小写字母写field - VS 2010 只是不断更正它。

                    为了使 VB.NET 中的派生类可以轻松访问它,必须提出另一种命名约定。为下划线加前缀可能是其中最不干扰和最“历史接受”的。

                    【讨论】:

                      【解决方案15】:

                      就 C 和 C++ 语言而言,名称中的下划线没有特殊含义(开头、中间或结尾)。它只是一个有效的变量名字符。 “约定”来自编码社区内的编码实践。

                      正如上面各种示例已经表明的那样,开头的 _ 可能表示 C++ 中类的私有或受保护成员。

                      让我只提供一些可能是有趣的琐事的历史。在 UNIX 中,如果您有一个核心 C 库函数和一个内核后端,并且您希望将内核函数暴露给用户空间,那么 _ 会卡在直接调用内核函数而不做任何其他事情的函数存根前面。最著名和最熟悉的例子是 BSD 和 SysV 类型内核下的 exit() 与 _exit() :在那里,exit() 在调用内核的退出服务之前执行用户空间的操作,而 _exit 只是映射到内核的退出服务。

                      所以 _ 用于“本地”的东西,在这种情况下本地是机器本地的。通常 _functions() 是不可移植的。因为你不应该期望在不同的平台上出现相同的行为。

                      现在对于变量名中的_,比如

                      int _foo;

                      从心理上讲,开头必须输入一个 _ 是一件很奇怪的事情。因此,如果您想创建一个与其他内容发生冲突的可能性较小的变量名,特别是在处理您想要的预处理器替换时,请考虑使用 _。

                      我的基本建议是始终遵循编码社区的惯例,以便更有效地协作。

                      【讨论】:

                        【解决方案16】:

                        现在,在 this.foobarbaz 中使用“this”的符号对于 C# 类成员变量是可以接受的。它取代了旧的“m_”或只是“__”符号。它确实使代码更具可读性,因为毫无疑问所引用的内容。

                        【讨论】:

                          【解决方案17】:

                          _var 没有任何意义,只是为了更容易区分变量是私有成员变量。

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

                          【讨论】:

                            【解决方案18】:

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

                            以下划线或双下划线开头的名称为 C++ 实现者保留。带有下划线的名称是为库保留的。

                            如果您阅读过 C++ 编码标准,您会在第一页看到它说:

                            “不要过度规范命名,但要使用一致的命名约定:只有两个必须做的事情:a) 永远不要使用“低调的名称”,即以下划线开头或包含双下划线的名称;” (p2,C++ 编码标准,Herb Sutter 和 Andrei Alexandrescu)

                            更具体地说,ISO working draft 说明了实际规则:

                            此外,有些标识符是为 C++ 实现保留使用的,否则不得使用;不需要诊断。 (a) 每个包含双下划线 __ 或以下划线后跟大写字母的标识符都保留给实现以供任何使用。 (b) 每个以下划线开头的标识符都保留给实现,用作全局命名空间中的名称。

                            最好避免以下划线开头的符号,以防您不小心陷入上述限制之一。

                            您自己就会明白为什么在开发软件时使用下划线会造成灾难性的后果:

                            尝试像这样编译一个简单的 helloWorld.cpp 程序:

                            g++ -E helloWorld.cpp
                            

                            您将看到在后台发生的所有事情。这是一个sn-p:

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

                            您可以看到有多少名称以双下划线开头!

                            此外,如果您查看虚拟成员函数,您会发现 *_vptr 是为虚拟表生成的指针,当您在类中使用一个或多个虚拟成员函数时,它会自动创建!但那是另一回事了……

                            如果您使用下划线,您可能会遇到冲突问题,并且您将不知道是什么原因造成的,直到为时已晚。

                            【讨论】:

                            • 不是全局或文件范围且以下划线和小写字母开头的名称不是很好吗?我一直这样做是因为它对于特定情况非常干净,例如: void A::set_size(int _size) { size = _size; }。对于这样的琐碎用途,你会做什么?
                            • 我相信在非全局/文件范围内允许下划线后跟小写字母。你能告诉我它在标准中的哪个地方说不是吗?尾随下划线的问题是我有时已经将它用于成员变量。所以我可能有函数'int size();'成员 var 'int size_;'和参数'int _size'。这往往很好地涵盖了事情,我还没有看到更好的选择。对于使用 STL 的泛型,大写的 func 是不可能的。 C# 人们喜欢的“this.size”样式对我来说似乎很容易出错,除非你总是将它用于丑陋的成员访问。
                            • 我理解有些人不想使用下划线和小写字母,因为他们可能难以清楚什么是合法的。 C++ 标准允许它,即使一些作者不建议使用它。对我来说,由于它是完全合法的并且没有保留,我认为没有任何理由认为它有风险。感谢您的反馈。
                            • @tukra:这不是完全合法的。 C++ 标准 允许您在本地范围内使用单个下划线后跟一个小写字母。祝你好运! :-)
                            • 对不起。我以为我们已经不需要重复资格了。在文件范围以外的每个范围中都允许使用以下划线后跟小写字母开头的 C++ 标识符。它在函数、函数原型、类、结构、联合、枚举以及您放入命名空间中的所有内容中都是安全且合法的。如果您遵循将所有代码放在命名空间中的常见做法,那么您是完全安全的。
                            【解决方案19】:

                            老问题,新答案 (C#)。

                            C# 下划线的另一个用途是与 ASP NET Core 的 DI(依赖注入)一起使用。在构造期间分配给注入接口的类的私有readonly 变量应以下划线开头。我想是否为类的每个私有成员使用下划线是一个争论(尽管微软自己也遵循它),但这是肯定的。

                            private readonly ILogger<MyDependency> _logger;
                            
                            public MyDependency(ILogger<MyDependency> logger)
                            {
                                _logger = logger;
                            }
                            

                            编辑:

                            一段时间以来,Microsoft 对类的所有私有成员都采用了下划线。

                            【讨论】:

                              猜你喜欢
                              • 2012-04-04
                              • 1970-01-01
                              • 2010-09-19
                              • 2011-03-13
                              • 2011-10-16
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2011-07-26
                              相关资源
                              最近更新 更多