C#中的匈牙利符号

时间:2009-04-20 13:30:03

标签: c# naming-conventions

在使用C#之前,C ++是我的主要编程语言。匈牙利的符号深藏在我心中。

我在C#做了一些小项目而没有阅读C#书或其他语言指南。在那些小型的c#项目中,我使用了类似

的东西
private string m_strExePath;

直到我从SO中读到的东西说:

  

不要使用匈牙利表示法。

为什么?我是唯一一个在我的C#代码中有m_strExePath或m_iNumber的人吗?

19 个答案:

答案 0 :(得分:48)

Joel Spolsky在这个主题上有一个非常好的article。快速总结是在实践中使用了两种类型的匈牙利表示法。

第一个是“匈牙利系统”,您可以使用前缀指定变量类型。像字符串“str”的东西。这几乎是无用的信息,特别是因为现代IDE会告诉你这种类型。

第二个是“Apps Hungarian”,您可以使用前缀指定变量的目的。最常见的例子是使用“m_”来表示成员变量。如果正确完成,这可能非常有用。

我的建议是避免像瘟疫这样的“匈牙利系统”,但肯定会使用“有用的匈牙利语”。我建议阅读乔尔的文章。它有点啰嗦,但解释得比我好多了。

本文最有趣的部分是匈牙利符号的最初发明者Charles Simonyi创作了“Apps Hungarian”,但他的论文被错误地解释了,因此创造了“匈牙利系统”的憎恶。

答案 1 :(得分:32)

在进行用户界面设计时,我发现维护匈牙利表示法非常有用。文本框,标签和下拉列表等项目更容易快速理解,并且通常会重复控制名称:

lblTitle = Label
txtTitle = TextBox
ddlTitle = DropDownList

对我来说,更容易阅读和解析。否则,由于IDE的进步,特别是Visual Studio,匈牙利符号不适合。

此外,Joel on Software有一篇与匈牙利符号相关的优秀文章:Making Wrong Code Look Wrong,其中有一些好的论据用于匈牙利符号。

答案 2 :(得分:30)

你不是唯一的人,但我会说这是相对不常见的。就个人而言,我不是匈牙利符号的粉丝,至少在简单的意义上不是只重述声明中已经存在的类型信息。 (“真正的”匈牙利符号的粉丝会解释它的区别 - 它从来没有让我感到困扰,但我可以看到他们的观点。如果你使用一个共同的前缀,比如长度单位与重量单位,你不会意外使用权重值分配长度变量,即使两者都可能是整数。)

但是,对于私人会员,您几乎可以按照自己的意愿行事 - 与您的团队达成一致意见。重要的是,如果您希望 API 适合.NET的其余部分,请不要在公共成员中使用匈牙利表示法(包括参数)。

答案 3 :(得分:21)

不,你不是唯一一个这样做的人。人们普遍认为,匈牙利符号并不是用C#命名事物的最佳方式(IDE处理了匈牙利符号试图解决的问题)。

答案 4 :(得分:13)

使用任何语言,匈牙利符号是一个可怕的错误。你也不应该在C ++中使用它。为变量命名,以便了解它们的用途。不要将它们命名为IDE可以提供给你的重复类型信息,并且可能会改变(并且通常无关紧要。如果你知道某些东西是一个计数器,那么它是无论是int16,32还是无关紧要64.你知道它作为一个计数器,因此,任何在计数器上有效的操作都应该是有效的.X / Y坐标的相同参数。它们是坐标。如果它们是浮点数或者它们无关紧要双倍。知道一个值是否以重量,距离或速度为单位可能是相关的。它是浮点数并不重要。)。

事实上,匈牙利的符号只是作为一种误解而出现的。发明者原本打算用它来描述一个变量的“概念”类型(它是一个坐标,一个索引,一个计数器,一个窗口?)

阅读他的描述的人认为通过“类型”他意味着实际的编程语言类型(int,float,零终止字符串,char指针)

这绝不是意图,这是一个可怕的想法。它复制了IDE可以更好地提供的信息,并且首先不是所有相关的信息,因为它鼓励您以尽可能低的抽象级别进行编程。

  

为什么?我是唯一拥有的人吗?   我的C#中的m_strExePathm_iNumber   码?

没有。不幸的是。告诉我,如果不是字符串,exePath会是什么?作为代码的读者,为什么我需要知道它是一个字符串?知道它是可执行文件的路径是不够的? m_iNumber的名字很糟糕。 哪个号码是这个?它适用于什么?你刚刚告诉我两次它是一个数字,但我仍然不知道这个数字是什么意思。

答案 5 :(得分:10)

你当然不是唯一一个人,但我确实希望你成为下降趋势的一部分:)

匈牙利表示法的问题在于它试图通过命名约定来实现类型系统。这是非常有问题的,因为它是一个只有人工验证的类型系统。项目中的每个人都必须同意相同的标准集,进行严格的代码审查并确保为所有新类型分配适当且正确的前缀。简而言之,用足够大的代码库来保证一致性是不可能的。在这一点上没有一致性你为什么要这样做?

此外,工具不支持匈牙利表示法。这似乎是表面上的愚蠢评论,但考虑重构。匈牙利命名约定系统中的每次重构都必须伴随大量重命名,以确保维护前缀。批量重命名容易受到各种微妙错误的影响。

不是使用名称来实现类型系统,而是依赖于类型系统。它具有自动验证和工具支持。较新的IDE可以更容易地发现变量的类型(智能感知,悬停提示等),并真正消除了对匈牙利符号的原始愿望。

答案 6 :(得分:6)

匈牙利表示法的一个缺点是开发人员经常在早期编码期间更改变量的类型,这需要变量的名称也发生变化。

答案 7 :(得分:5)

匈牙利符号的真正价值可以追溯到C编程和指针的弱类型性质。基本上,在当天,追踪类型的最简单方法是使用匈牙利语。

在像C#这样的语言中,类型系统会告诉您所有需要知道的内容,IDE会以非常友好的方式向您展示,因此根本不需要使用匈牙利语。

至于不使用它的充分理由,有很多。首先,在C#中,就C ++和其他许多因素而言,你经常创建自己的类型,那么“MyAccountObject”类型的匈牙利语是什么?即使您可以决定合理的匈牙利语符号,它仍然会使实际的变量名称稍微难以阅读,因为您必须在开始时跳过“LPZCSTR”(或其他)。更重要的是维护成本,如果你开始使用List并更改为另一种类型的集合(我现在似乎做了很多事情)怎么办?然后,您需要重命名使用该类型的所有变量,这些变量都没有真正的好处。如果您刚刚开始使用一个不错的名称,则不必担心这一点。

在您的示例中,如果您创建或使用了一些更有意义的类型来保存路径(例如路径),那么您需要将m_strExePath更改为m_pathExePath,这很痛苦。这种情况实际上并没有很大帮助。

答案 8 :(得分:5)

除非您使用的是文本编辑器而不是VS IDE,否则匈牙利符号几乎没有价值,它会妨碍而不是提高可读性

答案 9 :(得分:3)

我目前看到任何形式的匈牙利符号的唯一两个区域是:

  • 类成员变量,带有前导下划线(例如_someVar
  • WinForms和WebForms控件名称(Button的btn,Label的lbl等)

成员变量的主要下划线似乎与我们待了一段时间,但我希望看到匈牙利人对控制名称的影响力减弱。

答案 10 :(得分:1)

如果您和您的团队以及您公司的心脏深处的匈牙利符号,请务必使用它。就博客和书籍而言,它已不再被视为最佳实践。

答案 11 :(得分:1)

大多数匈牙利语符号描述变量是什么(指针,指针指针,指针内容等),以及它指向的是什么(字符串等)。

我发现在C#中很少使用指针,尤其是当没有非托管/ pinvoke调用时。此外,没有选择使用void *所以匈牙利语不需要描述它。

我(以及C#land中的大多数其他人)使用匈牙利语的唯一遗留,是在_的私人字段之前,如_customers;

答案 12 :(得分:1)

如果你把指针放在VS中的变量上它会告诉你它是什么类型的变量,所以没有理由使用这些神秘的变量名,特别是来自其他语言的人可能需要维护代码,它将成为易于阅读的障碍。

答案 13 :(得分:0)

在像C#这样的语言中,对于变量名长度的许多限制不存在曾经在C和C ++等语言中,并且IDE为确定变量的类型提供了极好的支持,匈牙利符号是多余的。

代码应该是不言自明的,因此m_szName之类的名称可以替换为this.name。并且m_lblName可以是nameLabel等。重要的是保持一致并创建易于阅读和维护的代码 - 这是任何命名约定的目标,因此您应该始终根据此决定使用哪种约定。我觉得匈牙利语符号不是最易读或最易维护的,因为它可能太简洁,需要对前缀的含义有一定的了解,并且不是语言的一部分,因此难以强制执行且难以检测当名称不再与基础类型匹配时。

相反,我喜欢通过引用成员的this来替换匈牙利应用程序(前缀为m_),引用静态变量的类名,并且没有局部变量的前缀。而不是系统匈牙利语(包括变量名中变量的类型),我更喜欢描述变量的内容,例如nameLabel,nameTextBox,count和databaseReference。

答案 14 :(得分:0)

在某些时候,你可能有一个属性

public string ExecutablePath { ... }

(不是说你应该尽量避免像“Exe”这样的缩写)。在这种情况下,你的问题可能在很多时候都没有用,因为你可以使用C#3.0的自动属性

public string ExecutablePath { get; set; }

您现在不再需要为后备存储变量提供名称。关于命名约定没有名称,没有问题/辩论。

显然,自动实现的属性并不总是合适的。

答案 15 :(得分:0)

这取决于。

足够重要在方法/类中添加变量/对象名称中数据类型的描述吗?

系统匈牙利表示法>应用程序匈牙利表示法

如果您使用过程语言(例如C)进行设计,其中包含许多全局变量或/和较低API,以处理精确的数据类型和大小(例如C <stdint.h>,其中40多种不同的数据类型符号是用于描述int),匈牙利语系统表示法更有帮助。

但是,请注意,许多现代程序员认为以变量名称添加类型信息非常丰富,因为许多现代IDE都有非常方便的工具(例如Eclipse的Outline,Xcode的Symbol Navigator,{{3} Visual Studio等)。系统匈牙利表示法在早期的编程中被广泛使用(例如FORTRAN,C99),当类型信息不能作为IDE的工具提供时。

系统匈牙利表示法&lt;应用程序匈牙利表示法

如果您正在使用更高级别的类或方法(例如,用于C#应用程序的用户定义的驱动程序类/方法),则表示简单数据类型可能不足以描述变量/对象。因此,在这种情况下,我们使用Apps Hungarian Notation。

例如,如果您的方法的目的是检索可执行路径并显示错误消息(如果未找到),而不是注意它是string的类型,我们会注意到更多重要信息来描述变量/对象让程序员更好地理解变量/ obejct的目的:

private string mPathExe;
private string msgNotFound;

答案 16 :(得分:0)

这是关于效率的。浪费了多少时间为变量分配错误的值。准确的变量声明是关于效率的提高。这是关于可读性的。它关注现有模式。如果你想要创造力,做用户界面设计,做系统架构。如果您的编程,它应该旨在让您的团队成员工作更轻松:不是您的。效率提高2%是每年额外的一周。那是40个小时。通过提高效率来提高人的生产力。

答案 17 :(得分:0)

匈牙利表示法首次使用BCPL编程语言。 BCPL是 Before C Programming Language 的缩写,是一种古老的(1966年设计)无类型语言,其中一切都是 word 。在这种情况下,匈牙利表示法可以帮助进行肉眼检查。

从那时起已经过了很多年......

这是最新的Linux kernel documentation所说的(大胆的):

  

将函数类型编码到名称中(所谓的匈牙利语   符号)是脑损伤 - 编译器无论如何都知道类型   检查那些,它只会让程序员感到困惑。

请注意匈牙利表示法有两种类型:

  • 系统匈牙利表示法:前缀对物理数据类型进行编码。

  • 应用匈牙利语符号:前缀对逻辑数据类型进行编码。

系统由于类型检查冗余而不再推荐使用匈牙利表示法,而冗余又是由于编译器功能的提升所致。但是,如果编译器不为您检查逻辑数据类型,您仍可以使用Apps匈牙利表示法。根据经验,匈牙利语符号是好的,当且仅当它描述了其他方式无法获得的语义。

答案 18 :(得分:0)

我不在乎,我总是将匈牙利语和Pascal / Camel Case结合使用。

不是用于数据类型,而是用于控件。因为txtName非常不言自明。某些人将其命名为NameTextBox,该名称太长。 lblAge,txtName,rdoTrue,cboCities,lstAccountInfo。美观,快速,紧凑 对于变量,普通变量和属性为Pascal情况。 “ firstName = txtFName.Text”(严重的是,如果您看不到它,并且意识到它是一个文本框,请谢兹)。然后,我将使用Camel Case作为方法

public void PrintNames (string fName, string lName)
{
    lblFullName.Text=fName + " " + lName;
}

是的,我用匈牙利的情况下,所以起诉我。没有人可以说他们不知道这些变量是什么,我希望能够快速查看而不必将鼠标悬停在变量的类型或控件上。刚开始编程时,我对所有变量都使用了全部上限,因此这是一个增强。为了可惜,不要在行尾放置大括号。很好,很对称。