关于c#:变量前缀(“匈牙利表示法”)是否真的有必要?

Are variable prefixes (“Hungarian notation”) really necessary anymore?

既然C是强类型的,我们真的需要给变量加前缀吗?

例如

1
2
3
iUserAge
iCounter
strUsername

我过去常常用前缀,但今后我看不到任何好处。


Are variable prefixes ( Hungarian ) really necessary anymore?

不!

事实上,微软自己的风格指南(实践的发源地)现在建议不要这样做。特别是,请参见有关通用命名约定的部分,其中包括以下文本(粗体,不少于):

Do not use Hungarian notation.


唯一适合弯曲标准和前缀变量的地方:

  • 对照组的名字:txtWhatever,我知道我不是唯一一个。好的是,你可以在txtname旁边找到类似lblname的东西,而且你不需要进入namelabel/nametextbox的方向。

  • 类成员变量:_whatever。我试过了m ou和no前缀,结果只使用了简单的下划线。M_u更难输入,没有前缀有时会让人感到困惑(特别是在维护期间,我知道所有人在编写代码时都会记住他们的代码)

但是,我没有发现任何一致的情况,在这种情况下,用变量的类型前缀将使代码更可读。

编辑:我读过微软的指导方针。然而,我认为在适当的情况下,允许编码样式发展和/或"弯曲"。正如我上面提到的,我发现使用下划线前缀在尝试和错误中很有用,而且肯定比使用这个更好。无论代码中的任何地方。

支持"进化"理论-早在.NET 1.x中,当微软发布编码指南时,他们就建议使用camel大小写来处理所有事情,甚至是常量。我现在看到了,它们已经改变了,建议对常量或公共只读字段使用pascal大小写。

此外,即使.NET框架类库目前也充满了m_uu和s_u(尝试使用Reflector浏览实现)。所以,毕竟,这取决于开发人员,只要在整个项目中保持一致性。


如果匈牙利语的意思是"前缀与类型缩写",如ucount或pchzname,那么我会说,这种做法是不好的,谢天谢地,似乎正在从常用的褪色。

但是,我仍然认为前缀对于范围非常有用。在我的工作室中,我们使用这个约定来预先固定变量:

1
2
3
4
5
6
7
i_  // input-only function parameter (most are these)
o_  // output-only function parameter (so a non-const & or * type)
io_ // bidirectional func param
_   // private member var (c#)
m_  // private member var (c++)
s_  // static member var (c++)
g_  // global (rare, typically a singleton accessor macro)

我觉得这个很有用。func参数前缀尤其有用。在函数内部,您总是可以一眼就知道var来自何处。通常,当我们想要修改它或改变它的含义时,我们将把var复制到另一个。

简而言之:对于现代工具,类型的前缀是不必要的。IDE负责为您识别和检查这些东西。但是基于范围的前缀对于可读性和清晰性非常有用。

还有一些有趣的好处,比如智能感知。您可以键入i_uuctrl space并获取要从中选择的func的所有输入参数。或者用空格键来获得所有的单件物品。节省时间。


不。我们需要吗?


匈牙利符号很难看。唯一的例外是接口,大多数人认为它是可接受的。

利纳斯总结得很好:将函数的类型编码到名称中(所谓的匈牙利符号)是大脑受损的-编译器无论如何都知道类型并可以检查这些类型,它只会混淆程序员。


不需要。匈牙利符号只是在代码中添加了不必要的噪声,对于编译器类型检查来说是多余的。


是的,如果匈牙利符号是按原意使用的,而不是按微软所实现的。与上面的示例非常相似,它将文本框和相应的标签显示为lblHatever、txtHatever。使用它来定义变量的使用,而不是类型。它可以提供信息来知道您的数字是moneytotal,这不仅告诉我数据类型。

但是,像通常使用的那样?不。


我看到的反对匈牙利符号的大多数论据都提到,现代的编辑器和IDES完全能够为您提供关于每个标识符所需的所有信息。很公平。

但是打印的代码呢?你不在纸上进行代码审查或演练吗?你不把印刷的代码用于培训吗?你不把代码片段用于在线帮助吗?匈牙利符号在这些场合非常有价值。

我在所有代码中一直使用(某种)匈牙利符号。我发现它的缺失是丑陋的,缺乏信息。


匈牙利符号不再需要像在字符串示例中那样标识数据类型,但它仍然可以用其他方式标识变量的特征。下面是一篇好文章,介绍使用匈牙利符号的有用方法:http://www.joelonsoftware.com/article s/wrong.html

这是摘录

"在Simonyi的匈牙利符号版本中,每个变量前面都有一个小写标记,表示变量所包含的类型。

例如,如果变量名是rwcol,则rw是前缀。

我是故意使用kind这个词的,因为Simonyi在他的论文中错误地使用了单词类型,而几代程序员都误解了他的意思。"

他还使用了一个识别前缀为"s"或"u"的字符串的示例来识别它们是否安全地打印出来,以便像print(usomestring)这样的语句很容易被识别为错误。


前缀是vb(和更旧的!)匈牙利符号是国王的日子。这种情况已经不复存在了,尽管C社区确实要求在接口(如ILoadable)中使用大写的I前缀。

下面是当前的微软指南。


好吧,我得说,这要看情况而定。我个人反对他们,但这取决于你的团队。每个团队都应该负责制定自己的指导方针。希望这不包括所谓的匈牙利符号,但它真的应该是一个团队的决定。您可能会发现需要打破样式准则的情况。


令我好奇的是,引入前缀(即匈牙利符号)的语言(C + +)也是强类型的。据我所知,这也是帕斯卡在微软的应用。而且它似乎也被用于Mesa,一种匈牙利人可能已经熟悉的强类型语言。

在这种情况下,我们可以深入研究这个问题,并考虑:(1)预混合用于帮助解决什么问题;(2)这个问题是如何消失的?

我知道这不是一个确切的答案,但它可能比笼统地反对使用过时或错误的前缀更有用。


我个人不再这样做了,但是你仍然会有人争论范围的前缀。

我和微软一起使用它们的大小写样式来处理所有的命名约定。在我看来,整个"类库开发人员设计指南"部分(链接是其中的一部分)都是纯金的。

另外,我喜欢Addison-Wesley的《框架设计指南》一书。它涵盖了所有这些指导原则,并附有来自微软团队成员的注释,说明他们为什么推荐他们的建议以及如何在组织内采用这些建议。


当然不是。一般来说,我开始相信这只是噪音。如果你是一个独立的顾问,或者你的公司没有一个全面的风格指南,那么Idesign有一个很好的指南。只需看看页面的右侧,您就可以通过D/L查询他们的C编码标准文档的最新版本。

史蒂夫


尽管编译器可以快速而容易地检查变量的类型,但是人类在浏览源代码时却无法这样做。因此,有些人(像我)喜欢将变量名变得稍微冗长一些,使它们可以快速识别为全局变量或类变量、字符串或int等。

它可能对编译器没有帮助,但是当读取一段外部代码时,它确实可以节省您必须手动查找每个变量的时间…


我只在我的数据库中使用它(PostgreSQL)

1
2
3
4
5
6
7
8
9
10
11
t_ for table name
v_ for view name
i_ for index name
trig_ for trigger


sp_ for stored procedure name
p_ for parameter    
v_ for variable
c_ for cursor
r_ for record

匈牙利表示法从未被用来显示变量的数据类型。有人误解说"str"或"i"用于隐式定义类型。它只显示变量的"种类",而不是"类型"。

因此,要回答这个问题,现在不应该使用它,过去也不应该使用它。

我知道它已经被链接了,但是滚动到Joel文章的底部了解更多信息-http://www.joelonsoftware.com/article s/wrong.html在那里他谈到匈牙利语在哪里


有关良好约定的概述,请参见以下内容:http://msdn.microsoft.com/en-us/library/ms229002.aspx

有一本书讲述了这些惯例背后的原因。读起来很有趣。


我总是在实例成员变量前面加上m_uuu,在静态成员变量前面加上s_u。我遇到过一些来自微软人的可变文章,他们推荐/反对这种方法。

我也很确定在使用Reflector浏览标准.NET库时遇到了m_u前缀…


不,我们不需要。我以前是这样做的,当时我们被迫遵循这种编码标准。

此外,有了IntelliSense、代码定义窗口和内置于VS中的重构工具以及其他第三方插件(如CodeRush Express和Refactor Pro),在没有它的情况下使用代码更容易。


在代码内部和处理数据类型时,我看不到使用匈牙利表示法的理由。

但是当我使用一系列用户界面控件时,无论它们是文本框、下拉列表、网格还是其他什么,我都喜欢让我的IntelliSense为我工作。为了实现这一点,我通常使用前缀为"uxsomecontrolname"的控件ID。这样,当我在寻找那个文本框来获取它的文本值时,我所要做的就是输入"ux",并显示所有的用户界面ID。无需搜索txt、ddl、grd或其他任何内容。

如果你读到上面的话,是这样吗?不,但是我不想坐着听,当我只需要知道两个字母的时候,试着记住十几个或更多的控制名称。

就像我说的,这只是在前端工作。


我一直在使用它,但那是可能的,因为我在Access和Excel中使用了VBA。

对我来说,countall是一个名称intcountall是一个具有这种区别的名称,它附加地描述了这个名称(从未用于机器,仅用于人类),就像sintcountall告诉我它的静态pintcountall private和gintcountall global一样,所以为了我使用它,它是非常有用的。

  • 控件名是一个更安全的时间,与controlName不同,我有lblControlName、txtControlName、cboControlName、lstcontrolName等,所以当我使用vba时,我只需键入lst,并具有我需要的所有名称,因此我不必记住确切的名称,这可以节省我很多时间,但这主要是Access和Excel中的vba。

当做埃米尔


我想说的是,现在大多数语言中,类型集有限,特别是没有无符号类型的概念,那么一个命名良好的变量不需要前缀。

在具有有符号和无符号类型的语言中,或者一系列类似的类型(例如short、int、long或int8、int16、in32),那么前缀是有用的,不管别人说什么(他们会说什么,你知道的)。

当您尝试在表达式中混合不同符号的整数类型时,编译器最多会发出警告,例如,如果您将IDE配置为仅在最终摘要中显示生成中的错误(而不是警告),则很容易忽略这一点(与使用Visual Studio一样)。在算术中混合符号会严重破坏你的一天,所以让你或你的继任者头疼并给他们一个线索。记住-你不是唯一一个看过代码的人。


虽然现在很多程序员都放弃了它,但在某些情况下我仍然会使用它。这里有一些;

  • 如果您维护的代码已经用过了,那我就留着使用它。

  • 当你的公司风格指导方针仍然需要或甚至建议它。

  • 当您的文档字母数字排序的列表变量,它帮助类类型分组。


对于C我唯一考虑的前缀是成员变量的a_,例如

1
2
3
4
public class Test
{
    private int _id;
}


有时我会使用一种前缀,其中pname是传递到我的函数的参数(注意,我不给类型加前缀),oname是当前方法的局部变量,mname是我所在类的成员,cname是常量或静态只读成员。

就我个人而言,我觉得这有帮助。


简短的回答是不,但是…

我明白摆脱匈牙利符号的意义,我们店里的标准也禁止它,但我仍然发现它在我的一次性或小型实用项目中很有用,原因只有一个:当我以web或win形式对大量控件进行编码时,使用hn使使用intellisense变得容易,确保我捕获每一个单独的con编码时出错。

如果我有五个复选框,它们的名字都以chk开头,那么输入chk会给我每个复选框的列表,我可以很容易地选择我正在处理的那个。

而且,有时我会想,"那个复选框又叫什么名字?"我必须停下来再看一次.aspx页面。

我妥协的一种方法是从hn开始,然后一旦我完成了win或web表单中的主代码,我的最后一步就是为hn命名的控件进行全局重命名。这对我来说真的很管用。当然了。


解决一个不存在的问题。


不,如果您的方法太长,以至于您无法在使用的同时读取定义,或者名称并不意味着类型,那么您的设计问题比命名问题更严重。

但是,我坚持使用它们的类型(如txtname)作为前缀控件。