为什么 var 会是一件坏事呢?
前几天我和同事聊天,听说他们的编码标准明确禁止他们在 C# 中使用 var
关键字。 他们不知道为什么会这样,而我总是发现隐式声明在编码时非常有用。 我在查找变量的类型时从来没有遇到过任何问题(您只需将鼠标悬停在 VS 中的变量上,就可以通过这种方式获得类型)。
有谁知道为什么在 C# 中使用 var 关键字是一个坏主意?
I've been chatting with my colleagues the other day and heard that their coding standard explicitly forbids them to use the var
keyword in C#. They had no idea why it was so and I've always found implicit declaration to be incredibly useful when coding. I've never had any problems finding out what type the variable was (you only hover over the variable in VS and you'll get the type that way).
Does anyone know why it would be a bad idea to use the var keyword in C#?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(18)
.Net 框架设计指南(很棒的书)的作者,于2008 年 11 月建议当类型明显且明确时考虑使用
var
。另一方面,如果使用
var
会导致阅读代码时出现歧义,正如 Anton Gogolev 指出的那样,那么最好不要使用它。在书中(附录 A)中,他们实际上给出了这个例子:
为了确保可读性不会受到低级开发人员的突发奇想,您的组织可能已经决定您不值得
var
并禁止了它。但遗憾的是,这就像你有一个很好的工具可供使用,但却把它放在一个上锁的玻璃柜里。
在大多数情况下,对简单类型使用
var
实际上有助于提高可读性,而且我们不能忘记,使用var
也不会带来性能损失。The writers of the .Net Framework Design Guidelines (awesome book) that came out in November 2008 recommend considering using
var
when the Type is obvious and unambiguous.On the other hand, if using
var
would result in an ambiguity when reading the code, as Anton Gogolev pointed out, then it's better not to use it.in the book (Annex A), they actually give this example:
It's possible that, to ensure that readability is not subjected to the whims of lowly developers, your organisation has decided that you were not worthy of
var
and banned it.It's a shame though, it's like having a nice tool at your disposal but keeping it in a locked glass cabinet.
In most cases, using
var
for simple types actually helps readability and we must not forget that there is also no performance penalty for usingvar
.确实是一件坏事。 然而,
对我来说完全没问题。
底线是:使用描述性标识符名称,您会相处得很好。
作为旁注:我想知道当不允许使用 var 关键字时,他们如何处理匿名类型。 或者他们根本不使用它们?
is indeed a bad thing. However,
is perfectly fine to me.
The bottomline is: use descriptive identifier names and you'll get along just fine.
As a sidenote: I wonder how do they deal with anonymous types when not allowed to use
var
keyword. Or they don't use them altogether?在大多数情况下,如果合理使用(即类型和值相同的简单类型初始值设定项),那就没问题。
有时,不清楚您是否通过更改来破坏了东西 - 主要是当初始化类型和(原始)变量类型不同时,因为:
在这些情况下,您可能会遇到任何类型解析的麻烦 - 例如:
在这种情况下,您可以更改代码的含义,并执行不同的操作。 那么这是一件坏事。
示例:
隐式转换:
方法隐藏:
等
In most cases when used sensibly (i.e. a simple type initializer where the type and value are the same), then it is fine.
There are some times when it is unclear that you've broken things by changing it - mainly, when the initialized type and the (original) variable type are not the same, because:
In these cases, you can get into trouble with any type resolution - for example:
In such cases, you change the meaning of the code, and execute something different. This is then a bad thing.
Examples:
Implicit conversion:
Method hiding:
etc
这当然是一个错误。 这是因为有些人没有意识到它实际上是强类型的,并且根本不像 VB 中的 var。
并非所有的公司编码标准都有意义,我曾经在一家公司工作过,该公司希望在所有类名称前加上公司名称前缀。 公司更名后进行了大规模的返工。
Surely this is a mistake. It's because some folk don't realise that it is actually strongly typed, and not at all like a var in VB.
Not all corporate coding standards make sense, I once worked for a company who wanted to prefix all class names with the company name. There was a massive rework when the company changed it's name.
首先,作为一般规则,编码标准应该由团队讨论和同意,并且应该写下它们背后的推理,以便任何人都可以知道它们为什么存在。 它们不应该是来自一位明师的神圣真理。
其次,这条规则可能是合理的,因为代码读取的次数多于写入的次数。
var
加快写入速度,但可能会减慢读取速度。 显然,这不是像“始终初始化变量”这样的代码行为规则,因为两种替代方案(编写var
和编写类型)具有完全相同的行为。 所以这不是一条关键规则。 我不会禁止var
,我只会使用“Prefer...”First, as a general rule, coding standards should be discussed and agreed by the team, and the reasoning behind them should be written down, so that anyone can know why they are there. They shouldn't be the Holy Truth from One Master.
Second, this rule is probably justified because code is more times read than written.
var
speeds up the writing, but may slow down the reading a bit. It's obviously not a code behaviour rule like "Always initialize variables" because the two alternatives (writingvar
and writing the type) have exactly the same behaviour. So it's not a critical rule. I wouldn't forbidvar
, I would just use "Prefer..."您可能认为 Microsoft 的观点是相关的,因为 C# 是他们的语言:
请参阅 MSDN - 隐式类型局部变量(C# 编程指南) ),最后一段。
您还应该注意 var 删除了初始分配的编译时数据类型测试。
由于大多数变量仅分配一次,因此一致使用 var 消除了几乎所有对变量分配的数据类型测试。
这使得您的代码容易受到意外更改的影响,例如合并工具或疲惫的开发人员所做的更改。
You may consider Microsoft's opinion to be relevant, since C# is their language:
See MSDN - Implicitly Typed Local Variables (C# Programming Guide), last paragraph.
You should also be aware that var removes the compile-time datatype test on the initial assignment.
Since most variables are only assigned once, consistent use of var removes almost all datatype tests on variable assignments.
This makes your code vulnerable to accidental changes e.g. those made by merge tools or tired developers.
几个月前我写了一篇关于这个主题的博客文章。 对我来说,我会尽可能地使用它,并围绕类型推断专门设计我的 API。 我使用类型推断的基本原因是
http://blogs.msdn .com/jaredpar/archive/2008/09/09/when-to-use-type-inference.aspx
I wrote a blog article on this topic a few months ago. For me, I use it every where possible and specifically design my APIs around type inference. The basic reasons I use type inference are
http://blogs.msdn.com/jaredpar/archive/2008/09/09/when-to-use-type-inference.aspx
var
是最新的“如何布置大括号”/匈牙利表示法/驼峰式大小写争论。 没有正确的答案,但有人采取极端的态度。你的朋友很不幸,他们在一名极端分子手下工作。
var
is the latest "how to lay out your braces"/hungarian notation/Camel casing debate. There is no right answer, but there are people who sit at the extremes.Your friend is just unfortunate they work below one of the extremists.
完全禁止它意味着禁止使用匿名类型(当您更多地使用 LINQ 时,匿名类型会变得非常有用)。
这是简单明了的愚蠢行为,除非有人能给出一个永远不使用匿名类型的充分理由。
Forbidding it entirely means forbidding the use of anonymous types (which become incredibly useful as you use LINQ more).
This is stupidity plain and simple unless someone can formalise a good reason to never use anonymous types.
用简单英语理解“var”
我将向您展示,使用和不使用“var”都是为了清晰地沟通。
我将展示使用“var”使代码更易于阅读的示例,以及使用 var 使事情难以理解的其他示例。
不仅如此,您还会发现“var”的清晰程度在很大程度上取决于您对代码中其他所有内容的命名。
举个例子:
谁走了另一条路? 杰克还是比尔? 在这种情况下,“Jake”和“Bill”就像类型名称。 而“He”和“him”就像var关键字。 在这种情况下,说得更具体可能会有所帮助。 下面的例子就更清楚了。
在这种情况下,更具体可以使句子更清晰。 但情况并非总是如此。 在某些情况下,具体化会使阅读变得更加困难。
在这种情况下,如果我们使用“he”并且在某些情况下将他的名字全部省略,那么阅读句子会更容易,这相当于使用
var
关键字。这些类比涵盖了要点,但并没有讲述整个故事。 在这些例子中看到只有一种方式来指代这个人。 要么用他们的名字,例如比尔,要么用更笼统的方式,如“他”和“他”。 但我们只用一个词。
对于代码,您有两个“单词”:类型和变量名称。
现在的问题是,是否有足够的信息可以让您轻松确定
p
是什么? 您是否仍然知道这种情况下的人是什么:这个怎么样:
这个怎么样:
或者这个:
或者这个:
关键字
var
在给定场景中是否有效很大程度上取决于代码的上下文,例如变量、类和方法的名称,以及代码的复杂性。我个人喜欢使用
var
关键字,它对我来说更全面。 但我也倾向于根据类型命名我的变量,这样我就不会真正丢失任何信息。也就是说,有时我会做出例外,这就是任何复杂事物的本质,而软件如果不复杂就什么都不是。
Understanding 'var' in Plain English
I'm going to show you that using AND not using 'var' is about communicating clearly.
I'm going to show examples of cases where using 'var' makes the code easier to read, and other examples when using var makes things hard to understand.
More than that you'll see that how clear 'var' is depends a lot on what you name everything else in your code.
Take this example:
Who went the other way? Jake or Bill? In this case "Jake" and "Bill" are like the type name. And "He" and "him" are like the var keyword. In this case it might help to be more specific. The following for example is much clearer.
In this case being more specific made the sentence clearer. But that's not always going to be case. In some cases being specific makes it harder to read.
In this case it would be easier to read the sentence if we used "he" and in some cases left out his name all together, this is the equivalent of using the
var
keyword.Those analogies cover the gist, but they don't tell the whole story. See in those examples there was only one way to refer to the person. Either with their name, for example Bill, or by a more general way, like "he" and "him". But we're only working with one word.
In the case of the code you have two "words", the type and the variable name.
The question now becomes is there enough information there for you to easily determine what
p
is? Would you still know what people is in this scenario:How about this one:
How about this one:
Or this one:
Or this one:
Whether the keyword
var
works in a given scenario depends a lot on the context of the code, like what the names of the variables, classes, and methods are, as well as the complexity of the code.Personally I like to use the
var
keyword it's more comprehensive to me. But I also tend to name my variables after the type so I'm not really losing any information.That said sometimes I make exceptions, such is the nature of anything complex, and software is nothing if not complicated.
如果滥用,可能会损害可读性。 然而,完全禁止它有点奇怪,因为如果没有它,你的同事将很难使用匿名类型。
It can hurt readability if it is misused. However completely forbidding it is a bit strange as your colleagues will have a tough time using anonymous types without it.
这确实是代码的可读性问题。
我个人的偏好是仅对匿名类型使用“var”(事实上,如果您想使用匿名类型,则需要使用 var),并且这些大多来自 LINQ 查询。 在这些情况下,如果您的查询投影到新的(隐式和匿名)类型,您别无选择,只能使用 var。
然而,C# 3.0 很乐意让您在 LINQ 和匿名类型之外的任何地方使用 var,例如:
是完全有效的,并且 myint 和 mystring 将通过用于初始化它们的推断值进行强类型化。 (因此,myint 是 System.Int32,mystring 是 System.String)。 当然,当查看用于初始化变量的值时,它们将被隐式类型化为什么类型,这是相当明显的,但是,我认为如果将上面的内容写为:
因为您可以立即看到, 那么代码的可读性会更好这些变量到底是什么类型。
考虑这个有点令人困惑的场景:
完全有效的代码(如果有点不传统),但在上面,我知道 bbb 是一个 double,尽管初始化值看起来是一个 int,但 aaa 绝对不会是一个 double,而是一个 double国际。
This is really a readability issue with your code.
My personal preference is to only ever use "var" for anonymous types (indeed, if you wish to use anonymous types at all, you'll need to use var), and these mostly come from LINQ queries. In these cases, you have no choice but to use var if your query is projecting into a new (implicit & anonymous) type.
However, C# 3.0 will happily let you use var anywhere you like, outside of LINQ and anonymous types, for example:
is perfectly valid, and myint and mystring will be strongly-typed by the inferred values used to initialize them. (thus, myint is a System.Int32 and mystring is a System.String). Of course, it's fairly obvious when looking at the values used to initialize the variables what types they will be implicitly typed to, however, I think it's even better for code readability if the above were written as:
since you can see immediately at a glance exactly which type those variables are.
Consider this somewhat confusing scenario:
Perfectly valid code (if a little unconventional) but in the above, I know that bbb is a double, despite the initializing value appearing to be an int, but aaa will definitely not be a double, but rather an int.
来自声明冗余部门(来自Jeff的编码恐怖):
我自己认为这值得考虑,但是制定一个关于何时使用或不使用的全面指南将矫枉过正。
From Department of Declaration Redundancy Department (from Jeff's Coding Horror):
I myself think it is worth taking about, but creating a comprehensive guideline on when to use or not would be overkill.
从 c# 9.0 开始,我们并不真正需要 var。
我们可以简单地
显式类型和短初始化。
as of c# 9.0 we don't really need var.
we can simply
explicit type and short init.
隐式类型很棒,而断然禁止它的人会损害生产力并导致脆弱的代码。
它几乎就像类型安全、编译器检查的鸭子类型,这在重构时非常有用。 例如,如果我有一个返回 List 的方法,并且我将其重构为返回 IEnumerable,则该方法的任何调用者使用 var 关键字并且仅使用 IEnumerable 方法都可以。 如果我已明确指定(例如 List),那么我必须在各处将其更改为 IEnumerable。
显然,如果任何隐式类型调用者需要 List 方法,那么我在构建时会收到编译错误,但如果是这种情况,我可能无论如何都不应该更改返回类型。
Implicit typing is great, and people who flat-out prohibit it damage productivity and invite brittle code.
It's almost like type-safe, compiler-checked duck typing, which is incredibly useful when refactoring. For example, if I have a method which returns a List, and I refactor it to return IEnumerable, then any callers to that method which have used the var keyword and only use IEnumerable methods will be fine. If I've explicitly specified, e.g., List, then I've got to go and change that to IEnumerable everywhere.
Obviously, if any of the implicit-typing callers require List methods, then I'll get compile errors when I build, but if that's the case I probably shouldn't have been changing the return type anyway.
Eric Lippert 求和it up well:
我自己的观点:我发现诸如
int
、string
、bool
甚至之类的类型更难阅读并且有点毫无意义用户。 毕竟,它与可读性有关(除了与 LINQ 一起使用的情况),因此当变量散布时,它可能会更难以阅读,并且违背了语言设计者想要的关键字的目的。
Eric Lippert sums it up well:
My own opinion: I find it harder to read and a bit pointless with types such as
int
,string
,bool
or even aUser
. It's about readability after all (except where using it with LINQ), so when vars are splattered about it can be harder to read and defeating the purpose of the keyword that the language designers intended it for.我曾经遇到过使用 var 导致类型属于某个基类而不是实际 DataRow 类型的情况(当我 foreach 遍历 Table.Rows 集合时)。 那是我唯一一次遇到 var 的麻烦。
I have had cases (when I foreach through a Table.Rows collection) when using var resulted in the type being of some base class rather than the actual DataRow type. That is the only time I have had trouble with var.
以下是我对
var
与显式键入的效率进行的测试的结果:第一个标签结果是:00:00:00 000034
第二个标签结果是:00:00:00 00008
Here are the results of a test I ran on efficiency of
var
versus explicit typing:First Label result is: 00:00:00 000034
Second Label result is: 00:00:00 00008