C# 为什么 var 是一件坏事?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/545616/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 07:38:06  来源:igfitidea点击:

Why would var be a bad thing?

c#coding-styleimplicit-typing

提问by Spoike

I've been chatting with my colleagues the other day and heard that their coding standard explicitly forbids them to use the varkeyword 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).

前几天我一直在和我的同事聊天,听说他们的编码标准明确禁止他们var在 C# 中使用关键字。他们不知道为什么会这样,我总是发现隐式声明在编码时非常有用。我从来没有遇到过任何问题,找出变量是什么类型(你只需将鼠标悬停在 VS 中的变量上,你就会以这种方式获得类型)。

Does anyone know why it would be a bad idea to use the var keyword in C#?

有谁知道为什么在 C# 中使用 var 关键字是个坏主意?

采纳答案by Renaud Bompuis

The writers of the .Net Framework Design Guidelines(awesome book) that came out in November 2008 recommend considering using varwhen the Type is obvious and unambiguous.

2008 年 11 月出版的.Net Framework Design Guidelines(很棒的书)的作者建议考虑var在类型明显且明确的情况下使用。

On the other hand, if using varwould result in an ambiguity when reading the code, as Anton Gogolev pointed out, then it's better not to use it.

另一方面,如果使用var会导致阅读代码时出现歧义,正如 Anton Gogolev 指出的那样,那么最好不要使用它。

in the book (Annex A), they actually give this example:

在书中(附件A),他们实际上给出了这个例子:

var names = new List<string>(); // good usage of var

string source = GetSource();
var tokens = source.Split(' '); // ok; most developers know String.Split

var id = GetId(); // Probably not good; it's not clear what the type of id is

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 varand 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.

有可能,为了确保可读性不受低级开发人员的奇思妙想,您的组织已经决定您不值得var并禁止它。
虽然很遗憾,但这就像您拥有一个不错的工具,但将其保存在上锁的玻璃柜中。

In most cases, using varfor simple types actually helps readability and we must not forget that there is also no performance penalty for using var.

在大多数情况下, using varfor simple types 实际上有助于提高可读性,我们不能忘记 using 也没有性能损失var

回答by NeedHack

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.

这肯定是一个错误。这是因为有些人没有意识到它实际上是强类型的,根本不像 VB 中的 var。

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.

并非所有公司编码标准都有意义,我曾经为一家公司工作,该公司希望在所有类名前加上公司名。公司更名后进行了大规模的返工。

回答by Andrew Hare

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.

如果被误用,它会损害可读性。然而完全禁止它有点奇怪,因为如果没有它,你的同事将很难使用匿名类型。

回答by Anton Gogolev

var q = GetQValue();

is indeed a bad thing. However,

确实是坏事。然而,

var persistenceManager = ServiceLocator.Resolve<IPersistenceManager>();

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 varkeyword. Or they don't use them altogether?

作为旁注:我想知道当不允许使用var关键字时,他们如何处理匿名类型。或者他们根本不使用它们?

回答by Garry Shutler

varis 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.

var是最新的“如何布置大括号”/匈牙利符号/骆驼套管辩论。没有正确的答案,但也有人站在极端。

Your friend is just unfortunate they work below one of the extremists.

你的朋友很不幸,他们在一名极端分子手下工作。

回答by ShuggyCoUk

Forbidding it entirely means forbidding the use of anonymous types (which become incredibly useful as you use LINQ more).

完全禁止它意味着禁止使用匿名类型(随着您更多地使用 LINQ,这变得非常有用)。

This is stupidity plain and simple unless someone can formalise a good reason to never use anonymous types.

这是一种简单明了的愚蠢,除非有人可以正式提出一个从不使用匿名类型的充分理由。

回答by Marc Gravell

In most cases when uses 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:

有时不清楚您是否通过更改破坏了事物 - 主要是当初始化类型和(原始)变量类型不相同时,因为:

  • the variable was originally the base-class
  • the variable was originally an interface
  • the variable was originally another type with an implicit conversion operator
  • 变量最初是基类
  • 该变量最初是一个接口
  • 该变量最初是另一种带有隐式转换运算符的类型

In these cases, you can get into trouble with any type resolution - for example:

在这些情况下,您可能会遇到任何类型解析的问题 - 例如:

  • methods that have different overloads for the two competing types
  • extension methods that are defined differently for the two competing types
  • members that have been re-declared (hidden) on one of the types
  • generic type inference will work differently
  • operator resolution will work differently
  • 对两种竞争类型具有不同重载的方法
  • 为两种竞争类型定义不同的扩展方法
  • 已在其中一种类型上重新声明(隐藏)的成员
  • 泛型类型推断的工作方式不同
  • 操作员分辨率将有所不同

In such cases, you change the meaning of the code, and execute something different. This is then a bad thing.

在这种情况下,您可以更改代码的含义,并执行不同的操作。那么这是一件坏事。

Examples:

例子:

Implicit conversion:

隐式转换:

static void Main() {
    long x = 17;
    Foo(x);
    var y = 17;
    Foo(y); // boom
}
static void Foo(long value)
{ Console.WriteLine(value); }
static void Foo(int value) {
throw new NotImplementedException(); }

Method hiding:

隐藏方法:

static void Main() {
    Foo x = new Bar();
    x.Go();
    var y = new Bar();
    y.Go(); // boom
}
class Foo {
    public void Go() { Console.WriteLine("Hi"); }
}
class Bar : Foo {
    public new void Go() { throw new NotImplementedException(); }
}

etc

等等

回答by Daniel Daranas

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. varspeeds 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 (writing varand writing the type) have exactly the same behaviour. So it's not a critical rule. I wouldn't forbid var, I would just use "Prefer..."

其次,这条规则可能是合理的,因为代码读取次数多于写入次数var加快写入速度,但可能会减慢读取速度。这显然不是像“始终初始化变量”这样的代码行为规则,因为这两种选择(写入var和写入类型)具有完全相同的行为。所以这不是一个关键规则。我不会禁止var,我只会使用“Prefer...”

回答by CraigTP

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.

我个人的偏好是只对匿名类型使用“var”(实际上,如果您想使用匿名类型,则需要使用 var),而这些主要来自 LINQ 查询。在这些情况下,如果您的查询投射到新的(隐式和匿名)类型,您别无选择,只能使用 var。

However, C# 3.0 will happily let you use var anywhere you like, outside of LINQ and anonymous types, for example:

但是,C# 3.0 很乐意让您在任何您喜欢的地方使用 var,在 LINQ 和匿名类型之外,例如:

var myint = 0;
var mystring = "";

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:

是完全有效的,并且 myint 和 mystring 将被用于初始化它们的推断值强类型化。(因此,myint 是 System.Int32 而 mystring 是 System.String)。当然,当查看用于初始化变量的值时,它们将被隐式键入的类型是相当明显的,但是,我认为如果将上述内容写成以下内容,则代码可读性会更好:

int myint = 0;
string mystring = "";

since you can see immediately at a glance exactly which type those variables are.

因为您可以一目了然地看到这些变量是哪种类型。

Consider this somewhat confusing scenario:

考虑这个有点令人困惑的场景:

var aaa = 0;
double bbb = 0;

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.

完全有效的代码(如果有点非常规)但在上面,我知道 bbb 是一个双精度值,尽管初始化值看起来是一个整数,但 aaa 绝对不是一个双精度数,而是一个整数。

回答by Ries

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 导致类型为某个基类而不是实际 DataRow 类型时的情况(当我通过 Table.Rows 集合进行 foreach 时)。那是我唯一一次遇到 var 问题。