前几天我和同事聊天,听说他们的编码标准明确禁止他们在C#中使用var
关键字。他们不知道为什么会如此,我总是发现隐式声明在编码时非常有用。我从来没有遇到任何问题,找出变量的类型(你只是将鼠标悬停在VS中的变量上,然后你就会得到那种类型)。
有谁知道为什么在C#中使用var关键字是个坏主意?
答案 0 :(得分:63)
2008年11月发布的.Net Framework Design Guidelines(很棒的书)的作者建议在类型明显且明确时使用var
。
另一方面,如果在阅读代码时使用var
会导致歧义,正如Anton Gogolev指出的那样,那么最好不要使用它。
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
为了确保可读性不受低级开发人员的影响,您的组织可能已经决定您不配var
并禁止它。
但这很遗憾,就像拥有一个漂亮的工具,但把它放在一个锁着的玻璃柜里。
在大多数情况下,对简单类型使用var
实际上有助于提高可读性,我们不要忘记使用var
也不会造成性能损失。
答案 1 :(得分:33)
var q = GetQValue();
确实是一件坏事。然而,
var persistenceManager = ServiceLocator.Resolve<IPersistenceManager>();
对我来说完全没问题。
底线是:使用描述性标识符名称,你会相处得很好。
作为旁注:我不知道如果不允许使用var
关键字,他们如何处理匿名类型。或者他们不完全使用它们?
答案 2 :(得分:17)
在大多数情况下,当合理使用时(即类型和值相同的简单类型初始化程序),那就没问题了。
有些时候不清楚你是通过改变它来破坏东西 - 主要是,当初始化类型和(原始)变量类型不相同时,因为:
在这些情况下,您可能会遇到任何类型分辨率的问题 - 例如:
在这种情况下,您可以更改代码的含义,并执行不同的操作。这是一件坏事。
示例:
隐式转换:
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(); }
方法隐藏:
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(); }
}
等
答案 3 :(得分:15)
当然这是一个错误。这是因为有些人没有意识到它实际上是强类型的,而且根本不像VB中的var。
并非所有公司编码标准都有意义,我曾经为一家想要在公司名称前加上所有类名称的公司工作过。当公司改名时,进行了大规模的返工。
答案 4 :(得分:8)
http://blogs.msdn.com/jaredpar/archive/2008/09/09/when-to-use-type-inference.aspx
答案 5 :(得分:7)
首先,作为一般规则,编码标准应该由团队讨论并达成一致,并且应该写下他们背后的推理,以便任何人都能知道他们为什么在那里。它们不应该是一位大师的圣洁真理。
其次,这条规则可能是合理的,因为代码的读取次数比写入的次数多。 var
加快了写作速度,但可能会减慢读数速度。它显然不是像“始终初始化变量”这样的代码行为规则,因为两个备选方案(编写var
并编写类型)具有完全相同的行为。所以这不是一个关键的规则。我不会禁止var
,我只会使用“首选...”
答案 6 :(得分:5)
var
是最新的“如何布置你的大括号”/匈牙利符号/骆驼套管辩论。没有正确答案,但也有人坐在极端。
你的朋友很幸运,他们在一个极端分子之下工作。
答案 7 :(得分:5)
禁止它完全意味着禁止使用匿名类型(当你更多地使用LINQ时,它会变得非常有用)。
这是愚蠢的简单和简单,除非有人能够正式确定永远不会使用匿名类型的正当理由。
答案 8 :(得分:4)
如果误用,可能会损害可读性。但是完全禁止它有点奇怪,因为没有它,你的同事将很难使用匿名类型。
答案 9 :(得分:3)
这实际上是您的代码的可读性问题。
我个人的偏好是只对匿名类型使用“var”(实际上,如果你想使用匿名类型,你需要使用var),这些主要来自LINQ查询。在这些情况下,如果您的查询投射到新的(隐式和匿名)类型,则别无选择,只能使用var。
但是,C#3.0很乐意让你在LINQ和匿名类型之外的任何地方使用var,例如:
var myint = 0;
var mystring = "";
完全有效,myint和mystring将通过用于初始化它们的推断值强类型化。 (因此,myint是System.Int32,mystring是System.String)。当然,在查看用于初始化变量的值时,相当明显的是它们将被隐式键入的类型,但是,如果将上述内容编写为:
,我认为它对代码可读性更好。int myint = 0;
string mystring = "";
因为您可以立即看到这些变量的确切类型。
考虑这个有点令人困惑的情况:
var aaa = 0;
double bbb = 0;
完全有效的代码(如果有点非常规)但在上面,我知道bbb是双精度的,尽管初始化值看起来是一个int,但是aaa肯定不是双精度,而是一个int。 / p>
答案 10 :(得分:3)
您可能认为Microsoft的观点是相关的,因为C#是他们的语言:
&#34;但是,使用 var 确实至少有可能使您的代码更难以理解为其他开发人员。因此,C#文档通常仅在需要时使用 var 。&#34;
请参阅MSDN - Implicitly Typed Local Variables (C# Programming Guide),最后一段。
您还应该知道 var 会删除初始分配的编译时数据类型测试。
var x = "mistake"; // error not found by compiler
int x = "mistake"; // error found
由于大多数变量仅分配一次,因此一致使用 var 会删除对变量赋值的几乎所有数据类型测试。
这使您的代码容易受到意外更改,例如那些由合并工具或疲惫的开发人员制作的。
答案 11 :(得分:2)
来自Department of Declaration Redundancy Department(来自杰夫的Coding Horror):
“我使用隐式变量输入 随时随地创建我的代码 更简洁。任何删除的东西 我们的代码应该是冗余 积极追求 - 达到和 包括切换语言。“
我自己认为它 值得一试,但是创建一个关于何时使用或不使用的综合指南将矫枉过正。
答案 12 :(得分:2)
隐式打字非常棒,而那些违规的人会禁止它会损害生产力并引发脆弱的代码。
这几乎就像是类型安全的,编译器检查的鸭子打字,这在重构时非常有用。例如,如果我有一个返回List的方法,并且我重构它以返回IEnumerable,那么使用var关键字并且只使用IEnumerable方法的那个方法的任何调用者都可以。如果我已明确指定,例如List,那么我必须将其更改为IEnumerable。
显然,如果任何隐式类型调用者需要List方法,那么在构建时我会遇到编译错误,但如果是这种情况,我可能不应该更改返回类型。
答案 13 :(得分:2)
Eric Lippert sums it up well:
我自己的观点:我发现阅读起来比较难,而int
,string
,bool
甚至是User
等类型都有点无意义。毕竟这是关于可读性的(除了在LINQ中使用它的情况除外),所以当vars被大肆宣传时,它可能更难以阅读并且无法达到语言设计者所希望的关键字的目的。
答案 14 :(得分:1)
我有一些情况(当我通过Table.Rows集合时),当使用var导致类型是某些基类而不是实际的DataRow类型时。这是我唯一一次遇到var。
答案 15 :(得分:0)
<强>&#39;无功&#39;是清楚
关于是否使用var
关键字的主要争论是关于代码对您和其他开发人员的可读性。
就像你在写一个故事一样,没有明确的正确答案。但是,让我们用简单的英语来看一些这方面的例子。
杰克向比尔打招呼。他不喜欢他,所以他转过身去了另一条路。
谁走了另一条路?杰克还是比尔?在这种情况下&#34; Jake&#34;和&#34;比尔&#34;就像类型名称。并且&#34;他&#34;和&#34;他&#34;就像var关键字一样。在这种情况下,它可能有助于更具体。以下例如更清楚。
杰克向比尔打招呼。杰克并不喜欢比尔,所以他转过身去了另一条路。
在这种情况下更具体地使句子更清楚。但情况并非总是如此。在某些情况下,具体化使得阅读更加困难。
比尔喜欢看书,所以比尔去了图书馆,比尔拿出了一本比尔一直喜欢的书。
在这种情况下,如果我们使用&#34;他会更容易阅读句子。并且在某些情况下,他们一起遗漏了他的名字,这相当于使用var
关键字。
比尔喜欢书,所以他去了图书馆并拿出了他一直喜欢的书。
这些类比涵盖了要点,但他们并不能讲述整个故事。在这些例子中,只有一种方式可以引用这个人。无论是他们的名字,比如比尔,还是通过更一般的方式,比如&#34;他&#34;和#34;他&#34;。但我们只用一个词来工作。
对于代码,您有两个&#34;单词&#34;,类型和变量名称。
Person p = GetPerson();
现在的问题是,是否有足够的信息可以让您轻松确定p
是什么?你还会知道在这种情况下人们是什么:
var p = GetPerson();
这个怎么样:
var p = Get();
这个怎么样:
var person = Get();
或者这个:
var t = GetPerson();
或者这个:
var u = Person.Get();
关键字var
在给定方案中是否有效取决于代码的上下文,例如变量,类和方法的名称,以及代码的复杂性。 / p>
就我个人而言,我喜欢使用var
关键字,对 me 更全面。但我也倾向于在类型之后命名我的变量,所以我并没有真正丢失任何信息。
那说有时候我会做出例外,这就是任何复杂事物的本质,如果不复杂,软件就没有任何意义。
答案 16 :(得分:-3)
以下是针对var
与显式输入的效率进行测试的结果:
private void btnVar_Click(object sender, EventArgs e)
{
Stopwatch obj = new Stopwatch();
obj.Start();
var test = "Test";
test.GetType();
obj.Stop();
lblResults.Text = obj.Elapsed.ToString();
}
private void btnString_Click(object sender, EventArgs e)
{
Stopwatch obj = new Stopwatch();
obj.Start();
string test = "Test";
obj.Stop();
lblResults.Text = obj.Elapsed.ToString();
}
First Label结果为:00:00:00 000034
第二个标签结果是:00:00:00 00008