在类字段中经常看到_var
变量名,下划线是什么意思?是否有关于所有这些特殊命名约定的参考资料?
在类字段中经常看到_var
变量名,下划线是什么意思?是否有关于所有这些特殊命名约定的参考资料?
下划线仅仅是一种惯例,没有其他意义。因此,其使用方式对每个人来说都有些不同。以下是我对两种编程语言的理解:
在 C++ 中,下划线通常表示私有成员变量。
在 C# 中,我通常只看到它被用于为公共属性定义底层私有成员变量。其他私有成员变量则不会带有下划线。然而,随着自动属性的出现,这种用法已经大大减少了。
之前:
private string _name;
public string Name
{
get { return this._name; }
set { this._name = value; }
}
之后:
public string Name { get; set; }
public string Name { get; private set; }
。确实,它并不完全是不可变的,但已经足够了。 - jdmichal_var
并不是保留的。 - Tyler McHenry在C++中最好不要在任何变量名或参数名之前使用下划线
以下划线或双下划线开头的名称是保留给C++实现者的。带下划线的名称被保留供库使用。
如果您查看C++编程标准,您将看到在第一页上它说:
"不要过度立法命名,但是要使用一致的命名约定:只有两个必须做的事情:a) 永远不要使用“欺诈性名称”,即以下划线开头或包含双下划线的名称;" (p2, C++编程规范,Herb Sutter和Andrei Alexandrescu)
更具体地,ISO工作草案规定了实际规则:(链接)
此外,某些标识符为C++实现所保留,并且不应用于其他用途;无需进行诊断。(a)每个包含双下划线__或以下划线后跟大写字母开头的标识符都保留供实现使用。 (b)以下划线开头的每个标识符都保留供实现在全局命名空间中用作名称。
最好不要以下划线开头一个符号,以防意外进入上述限制之一。
您可以自己看到为什么在开发软件时这种下划线的使用可能会灾难性:
尝试编译像这样的简单helloWorld.cpp程序:
g++ -E helloWorld.cpp
你将看到背景中发生的一切。这是一个片段: 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 是为虚表生成的指针,当你在类中使用一个或多个虚成员函数时,它会自动创建!但这是另外一个故事...
如果你使用下划线,你可能会遇到冲突问题,而且直到太晚才知道导致这个问题的原因。
实际上,_var
这种约定来自 VB,而不是 C# 或 C++(m_... 是另一回事)。
这是为了解决在声明属性时 VB 的大小写不敏感性问题。
例如,在 VB 中不可能编写如下代码,因为它会将 user
和 User
视为相同的标识符。
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 中,永远要指示“Protected”或“Private”,不要使用“Dim”。不建议使用“m_”,也不建议使用只有大小写区别的变量名,特别是在使用受保护的变量时,这会违反兼容性并使您的编程生涯备受痛苦,因为您必须为成员命名与访问器/变量名不同的内容。在所有项目中,下划线开头实际上是唯一具有争议的一个。个人而言,我更喜欢它,因为对于我的私有变量,我不必用“this.”限定变量名来区分构造函数或其他地方的参数,这样做是很重要的,因为 VB.NET 是不区分大小写的,因此您的访问器属性通常与您的私有成员变量具有相同的名称,除了下划线。至于“m_”,这真的只是关于美学方面的问题。我(和许多其他人)认为 m_ 很丑,因为它看起来像变量名中有一个洞。这几乎令人反感。我过去经常在 VB6 中使用它,但那仅仅是因为变量无法以下划线开头。我很高兴看到它消失了。Microsoft 建议不要使用 m_(也不要使用下划线),尽管他们在他们的代码中都使用了这两种方式。同时,以直接“m”作为前缀是行不通的。当然,由于他们主要使用 C# 编码,所以可以拥有仅在属性上区分大小写的私有成员。VB 用户必须做一些其他的事情。与其试图提出适用于每种语言的特殊情况,我建议对所有支持它的语言使用下划线作为前缀。如果我想让我的类完全符合 CLS,我可以在任何 C# 受保护的成员变量上省略前缀。不过,在实践中,我从不担心这个问题,因为我将所有潜在的受保护成员变量都保持为私有,并提供受保护的访问器和变量。为什么:简而言之,这个约定很简单(只有一个字符),易于阅读(您的眼睛不会被其他开头的字符分散注意力),并成功避免了过程级变量和类级属性之间的命名冲突。
_var没有实际意义,只是为了更容易地区分变量为私有成员变量。
在C++中,使用_var惯例是不好的形式,因为前面带下划线的标识符有规则。_var被保留作为全局标识符,而_Var(下划线+大写字母)则随时保留。这就是为什么在C++中,你会看到人们使用var_惯例。
_var
的代码可能是遗留代码,或者是由于成长环境使用旧的命名系统而编写的代码,这个系统不反对前导下划线。
正如其他答案所述,它曾经用于标识C++类成员变量。然而,就装饰器或语法而言,它没有特殊的含义。因此,如果您想使用它,它将被编译。
至于C#讨论,我会留给其他人。
旧问题,新答案(C#)。
C#中下划线的另一个用法是与ASP NET Core的DI(依赖注入)一起使用。类的私有readonly
变量在构造时被分配给注入的接口,应该以下划线开头。我想这是否对于类的每个私有成员都使用下划线存在争议(尽管Microsoft本身遵循此规则),但这个是确定的。
private readonly ILogger<MyService> _logger;
public MyService(ILogger<MyService> logger)
{
_logger = logger;
}
编辑:
微软现在已经采用下划线来表示类的所有私有成员。
在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 的派生类中易于访问,必须想出另一种命名约定。在前面添加下划线可能是最不侵入性且最“历史接受”的方法。