命名约定 - C++ 中的下划线和 C# 变量

发布于 2024-09-07 00:56:23 字数 65 浏览 3 评论 0原文

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

It's common to see a _var variable name in a class field. What does the underscore mean? Is there a reference for all these special naming conventions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(19

执手闯天涯 2024-09-14 00:56:23

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

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

在 C# 中,我通常只在为公共属性定义底层私有成员变量时才使用它。其他私有成员变量不会有下划线。不过,随着自动属性的出现,这种用法基本上已经被抛弃了。

之前:

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

之后:

public string Name { get; set; }

The underscore is simply a convention; nothing more. As such, its use is always somewhat different to each person. Here's how I understand them for the two languages in question:

In C++, an underscore usually indicates a private member variable.

In C#, I usually see it used only when defining the underlying private member variable for a public property. Other private member variables would not have an underscore. This usage has largely gone to the wayside with the advent of automatic properties though.

Before:

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

After:

public string Name { get; set; }
睡美人的小仙女 2024-09-14 00:56:23

最佳实践是在 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 是为虚拟表生成的指针,当您在类中使用一个或多个虚拟成员函数时,该指针会自动创建!但这是另一个故事了......

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

It is best practice to NOT use UNDERSCORES before any variable name or parameter name in C++

Names beginning with an underscore or a double underscore are RESERVED for the C++ implementers. Names with an underscore are reserved for the library to work.

If you have a read at the C++ Coding Standard, you will see that in the very first page it says:

"Don't overlegislate naming, but do use a consistent naming convention: There are only two must-dos: a) never use "underhanded names," ones that begin with an underscore or that contain a double underscore;" (p2 , C++ Coding Standards, Herb Sutter and Andrei Alexandrescu)

More specifically, the ISO working draft states the actual rules:

In addition, some identifiers are reserved for use by C ++ implementations and shall not be used otherwise; no diagnostic is required. (a) Each identifier that contains a double underscore __ or begins with an underscore followed by an uppercase letter is reserved to the implementation for any use. (b) Each identifier that begins with an underscore is reserved to the implementation for use as a name in the global namespace.

It is best practice to avoid starting a symbol with an underscore in case you accidentally wander into one of the above limitations.

You can see it for yourself why such use of underscores can be disastrous when developing a software:

Try compiling a simple helloWorld.cpp program like this:

g++ -E helloWorld.cpp

You will see all that happens in the background. Here is a snippet:

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

You can see how many names begin with double underscore!

Also if you look at virtual member functions, you will see that *_vptr is the pointer generated for the virtual table which automatically gets created when you use one or more virtual member functions in your class! But that's another story...

If you use underscores you might get into conflict issues and you WILL HAVE NO IDEA what's causing it, until it's too late.

戈亓 2024-09-14 00:56:23

实际上,_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 -命名约定和编程标准---最佳实践

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

Actually the _var convention comes from VB not C# or C++ (m_,... is another thing).

This came to overcome the case insensitivity of VB when declaring Properties.

For example, such code isn't possible in VB because it considers user and User as the same identifier

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

So to overcome this, some used a convention to add '_' to the private field to come like this

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

Since many conventions are for .Net and to keep some uniformity between C# et VB.NET convention, they are using the same one.

I found the reference for what I was saying :
http://10rem.net/articles/net-naming-conventions-and-programming-standards---best-practices

Camel Case with Leading Underscore. In
VB.NET, always indicate "Protected" or
"Private", do not use "Dim". Use of
"m_" is discouraged, as is use of a
variable name that differs from the
property by only case, especially with
protected variables as that violates
compliance, and will make your life a
pain if you program in VB.NET, as you
would have to name your members
something different from the
accessor/mutator properties. Of all
the items here, the leading underscore
is really the only controversial one.
I personally prefer it over straight
underscore-less camel case for my
private variables so that I don't have
to qualify variable names with "this."
to distinguish from parameters in
constructors or elsewhere where I
likely will have a naming collision.
With VB.NET's case insensitivity, this
is even more important as your
accessor properties will usually have
the same name as your private member
variables except for the underscore.
As far as m_ goes, it is really just
about aesthetics. I (and many others)
find m_ ugly, as it looks like there
is a hole in the variable name. It's
almost offensive. I used to use it in
VB6 all the time, but that was only
because variables could not have a
leading underscore. I couldn't be
happier to see it go away. Microsoft
recommends against the m_ (and the
straight _) even though they did both
in their code. Also, prefixing with a
straight "m" is right out. Of course,
since they code mainly in C#, they can
have private members that differ only
in case from the properties. VB folks
have to do something else. Rather than
try and come up with
language-by-language special cases, I
recommend the leading underscore for
all languages that will support it. If
I want my class to be fully
CLS-compliant, I could leave off the
prefix on any C# protected member
variables. In practice, however, I
never worry about this as I keep all
potentially protected member variables
private, and supply protected
accessors and mutators instead. Why:
In a nutshell, this convention is
simple (one character), easy to read
(your eye is not distracted by other
leading characters), and successfully
avoids naming collisions with
procedure-level variables and
class-level properties.class-level properties.

呆头 2024-09-14 00:56:23

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

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

_var has no meaning and only serves the purpose of making it easier to distinguish that the variable is a private member variable.

In C++, using the _var convention is bad form, because there are rules governing the use of the underscore in front of an identifier. _var is reserved as a global identifier, while _Var (underscore + capital letter) is reserved anytime. This is why in C++, you'll see people using the var_ convention instead.

短叹 2024-09-14 00:56:23

第一个评论者(R Samuel Klatchko)引用:在 C++ 标识符中使用下划线的规则是什么? 回答了有关 C++ 中下划线的问题。一般来说,您不应该使用前导下划线,因为它是为编译器的实现者保留的。您在 _var 中看到的代码可能是遗留代码,或者是由使用旧命名系统长大的人编写的代码,该命名系统不支持前导下划线。

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

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

The first commenter (R Samuel Klatchko) referenced: What are the rules about using an underscore in a C++ identifier? which answers the question about the underscore in C++. In general, you are not supposed to use a leading underscore, as it is reserved for the implementer of your compiler. The code you are seeing with _var is probably either legacy code, or code written by someone that grew up using the old naming system which didn't frown on leading underscores.

As other answers state, it used to be used in C++ to identify class member variables. However, it has no special meaning as far as decorators or syntax goes. So if you want to use it, it will compile.

I'll leave the C# discussion to others.

你的呼吸 2024-09-14 00:56:23

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

C# 下划线的另一个用途是 ASP NET Core 的 DI(依赖注入)。在构造过程中分配给注入接口的类的私有readonly变量应该以下划线开头。我想这是一个关于是否对类的每个私有成员使用下划线的争论(尽管微软本身遵循它),但这是肯定的。

private readonly ILogger<MyService> _logger;

public MyService(ILogger<MyService> logger)
{
    _logger = logger;
}

编辑:

Microsoft 对类的所有私有成员采用下划线已经有一段时间了。

Old question, new answer (C#).

Another use of underscores for C# is with ASP NET Core's DI (dependency injection). Private readonly variables of a class which got assigned to the injected interface during construction should start with an underscore. I guess it's a debate whether to use underscore for every private member of a class (although Microsoft itself follows it) but this one is certain.

private readonly ILogger<MyService> _logger;

public MyService(ILogger<MyService> logger)
{
    _logger = logger;
}

EDIT:

Microsoft adopted use of underscores for all private members of a class for a while now.

握住你手 2024-09-14 00:56:23

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

使用 _field 可以帮助 Intelilsense 过滤所有仅键入 _ 的类变量。

我通常遵循 Brad Adams 准则,但建议不要使用下划线。

You can create your own coding guidelines. Just write a clear documentation for the rest of the team.

Using _field helps the Intelilsense to filter all class variables just typing _.

I usually follow the Brad Adams Guidelines, but it recommends to not use underscore.

若无相欠,怎会相见 2024-09-14 00:56:23

对于 C#,Microsoft 框架设计指南 建议不要使用下划线字符来表示 公共成员。对于私有成员,可以使用下划线。事实上,Jeffrey Richter(经常在指南中引用)使用例如 m_,“s_”表示私有静态成员。

就我个人而言,我只使用 _ 来标记我的私人成员。 “m_”和“s_”接近匈牙利表示法,这不仅在.NET中令人不悦,而且可能非常冗长,我发现具有许多成员的类很难按字母顺序进行快速浏览(想象一下 10 个变量都以 m_ 开头) 。

With C#, Microsoft Framework Design Guidelines suggest not using the underscore character for public members. For private members, underscores are OK to use. In fact, Jeffrey Richter (often cited in the guidelines) uses an m_ for instance and a "s_" for private static memberss.

Personally, I use just _ to mark my private members. "m_" and "s_" verge on Hungarian notation which is not only frowned upon in .NET, but can be quite verbose and I find classes with many members difficult to do a quick eye scan alphabetically (imagine 10 variables all starting with m_).

节枝 2024-09-14 00:56:23

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

The Microsoft naming standard for C# says variables and parameters should use the lower camel case form IE: paramName. The standard also calls for fields to follow the same form but this can lead to unclear code so many teams call for an underscore prefix to improve clarity IE: _fieldName.

小苏打饼 2024-09-14 00:56:23

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

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

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

I use the _var naming for member variables of my classes. There are 2 main reasons I do:

1) It helps me keep track of class variables and local function variables when I'm reading my code later.

2) It helps in Intellisense (or other code-completion system) when I'm looking for a class variable. Just knowing the first character is helpful in filtering through the list of available variables and methods.

伏妖词 2024-09-14 00:56:23

在 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 中的派生类能够轻松访问它,必须提出另一种命名约定。前缀下划线可能是其中干扰性最小且最“历史上接受”的。

There is a fully legit reason to use it in C#: if the code must be extensible from VB.NET as well.
(Otherwise, I would not.)

Since VB.NET is is case insensitive, there is no simple way to access the protected field member in this code:

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

E.g. this will access the property getter, not the field:

Public Class VBClass
    Inherits CSharpClass

    Function Test() As Integer
        Return Field
    End Function

End Class

Heck, I cannot even write field in lowercase - VS 2010 just keeps correcting it.

In order to make it easily accessible to derived classes in VB.NET, one has to come up with another naming convention. Prefixing an underscore is probably the least intrusive and most "historically accepted" of them.

真心难拥有 2024-09-14 00:56:23

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

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

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

因此 _ 用于“本地”内容,在本例中本地是机器本地的。通常 _functions() 是不可移植的。因为您不应该期望在不同平台上有相同的行为。

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

int _foo;

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

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

As far as the C and C++ languages are concerned there is no special meaning to an underscore in the name (beginning, middle or end). It's just a valid variable name character. The "conventions" come from coding practices within a coding community.

As already indicated by various examples above, _ in the beginning may mean private or protected members of a class in C++.

Let me just give some history that may be fun trivia. In UNIX if you have a core C library function and a kernel back-end where you want to expose the kernel function to user space as well the _ is stuck in front of the function stub that calls the kernel function directly without doing anything else. The most famous and familiar example of this is exit() vs _exit() under BSD and SysV type kernels: There, exit() does user-space stuff before calling the kernel's exit service, whereas _exit just maps to the kernel's exit service.

So _ was used for "local" stuff in this case local being machine-local. Typically _functions() were not portable. In that you should not expect same behaviour across various platforms.

Now as for _ in variable names, such as

int _foo;

Well psychologically, an _ is an odd thing to have to type in the beginning. So if you want to create a variable name that would have a lesser chance of a clash with something else, ESPECIALLY when dealing with pre-processor substitutions you want consider uses of _.

My basic advice would be to always follow the convention of your coding community, so that you can collaborate more effectively.

世界等同你 2024-09-14 00:56:23

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

It's simply means that it's a member field in the class.

落花浅忆 2024-09-14 00:56:23

没有特定的单一命名约定,但我见过私人成员的命名约定。

There's no particular single naming convention, but I've seen that for private members.

夜清冷一曲。 2024-09-14 00:56:23

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

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

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

Many people like to have private fields prefixed with an underscore. It is just a naming convention.

C#'s 'official' naming conventions prescribe simple lowercase names (no underscore) for private fields.

I'm not aware of standard conventions for C++, although underscores are very widely used.

べ映画 2024-09-14 00:56:23

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

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

It's just a convention some programmers use to make it clear when you're manipulating a member of the class or some other kind of variable (parameters, local to the function, etc). Another convention that's also in wide use for member variables is prefixing the name with 'm_'.

Anyway, these are only conventions and you will not find a single source for all of them. They're a matter of style and each programming team, project or company has their own (or even don't have any).

绻影浮沉 2024-09-14 00:56:23

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

Now the notation using "this" as in this.foobarbaz is acceptable for C# class member variables. It replaces the old "m_" or just "__" notation. It does make the code more readable because there is no doubt what is being reference.

孤寂小茶 2024-09-14 00:56:23

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

From my experience (certainly limited), an underscore will indicate that it is a private member variable. As Gollum said, this will depend on the team, though.

油焖大侠 2024-09-14 00:56:23

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

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

这可以帮助人们在阅读不熟悉的代码时非常快速地理解成员的结构、使用、可访问性和位置。

A naming convention like this is useful when you are reading code, particularly code that is not your own. A strong naming convention helps indicate where a particular member is defined, what kind of member it is, etc. Most development teams adopt a simple naming convention, and simply prefix member fields with an underscore (_fieldName). In the past, I have used the following naming convention for C# (which is based on Microsofts conventions for the .NET framework code, which can be seen with Reflector):

Instance Field: m_fieldName
Static Field: s_fieldName
Public/Protected/Internal Member: PascalCasedName()
Private Member: camelCasedName()

This helps people understand the structure, use, accessibility and location of members when reading unfamiliar code very rapidly.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文