为什么ReSharper想把“var”用于一切?

我刚刚开始在Visual Studio中使用ReSharper(在SO之后的许多build议之后)。 尝试一下,我打开了一个最近的ASP.NET MVC项目。 我注意到的第一个也是最常见的事情之一就是将大部分/全部显式声明改为var 。 例如:

 //From This: MyObject foo = DB.MyObjects.SingleOrDefault(w => w.Id == 1); //To This: var foo = DB.MyObjects.SingleOrDefault(w => w.Id == 1); 

甚至简单的types,如intbool等等。

为什么这被推荐? 我不是来自计算机科学或.NET背景,最近已经“陷入”了.NET开发,所以我真的很想知道发生了什么,是否有益。

一个原因是提高了可读性。 哪个更好?

 Dictionary<int, MyLongNamedObject> dictionary = new Dictionary<int, MyLongNamedObject>(); 

要么

 var dictionary = new Dictionary<int, MyLongNamedObject>(); 

ReSharperbuild议显然过分使用var关键字。 你可以在types明显的地方使用它:

 var obj = new SomeObject(); 

如果types不明显,则应该写出来:

 SomeObject obj = DB.SomeClass.GetObject(42); 

我个人更喜欢closures这个build议。 使用var可以提高可读性; 但正如你所提到的,它有时会减less它(用简单的types,或者当结果types不清晰时 )。

我宁愿select什么时候使用var ,什么时候不使用。 但是,这只是我。

var可以提高代码的可读性,同时减less对代码的直接理解。 同样,它可以降低其他情况下的代码的可读性。 有时使用它是中立的。 理解的可读性的度量不是成正比的,而是取决于情况。 有时两者一起增加或减less。

这个因素是什么var被应用到目标支持立即模糊其数据types的读者,或者如果它的types信息需要了解手头的程序部分。

例如,错误的命名可能导致var导致代码理解的减less。 这不是var的错:

 var value1 = GetNotObviousValue(); //What's the data type? //vs. var value2 = Math.Abs(-3); // Obviously a numeric data type. 

有时,如果代码在不存在的情况下可读性更好,则将var用于简单数据types是没有意义的:

 var num = GetNumber(); // But what type of number? // vs. double num = GetNumber(); // I see, it's a double type. 

有时, var可以用来隐藏数据types信息,您不一定要关心以下的复杂性:

  IEnumerable<KeyValuePair<string,List<Dictionary<int,bool>>>> q = from t in d where t.Key == null select t; // OMG! //vs. var q = from t in d where t.Key == null select t; // I simply want the first string, so the last version seems fine. q.First().Key; 

当存在匿名types时,您必须使用var ,因为没有types名称可以通过以下方式调用它:

 var o = new { Num=3, Name="" }; 

如果您的Visual Studio Intellisense提供了types信息(无论是否为var ,那么您需要通过严格的代码读取来减less对您的理解。 假设不是每个人都可能拥有或使用智能感知,这可能是明智的。

综上所述,基于上面的例子,我build议单张应用var不是一个好主意,因为大多数事情最好是在适度的基础上,并根据这里所示的情况。

为什么Resharper默认使用它? 我build议放心,因为它不能parsing情况的细微差别,以决定何时最好不使用它。

在ReSharper(8.02,但可能是其他版本)中,可以通过首先打开ReSharper的选项菜单来调整“Use implicitly typed local variable declaration”build议的选项 ,无论如何,

ReSharper选项菜单

然后,在“代码检查”下,通过调整所选语言的“检查严重性”,在我的情况下,c#:

关闭隐式键入的局部变量建议

正如你所看到的,有一些选项可以调整ReSharper所做的所有build议。 希望这可以帮助像我这样已经有了“var”使用策略的人,只是希望ReSharper尊重它:)

我很惊讶,没有人提到,更改实例化对象的types也更容易,因为

 AVeryLongTypeName myVariable = new AVeryLongTypeName( arguments ); 

是一种重复forms 。 如果我想将AVeryLongTypeName更改为其派生类之一,则只需在使用var时更改一次,仍然可以访问子类的方法。

除此之外,提高可读性是一个重要的点,但正如其他人所说,var不应该过度使用,所以我认为在Resharper中提示是绝对没问题的。

我也不喜欢这个。

我不希望这变成关于var的使用的辩论,它有其用途,但不应该到处使用。

要记住的关键是ReSharperconfiguration为任何你想要的编码标准。

编辑: ReSharper和var

“var”即将清晰

关于是否使用var关键字的主要争议是关于代码对您和其他开发人员的可读性。

就像你正在写一个故事一样,没有确切的正确答案。 但是让我们以简单的英文来看看这个例子。

杰克和比尔问好。 他不喜欢他,所以他转过身去。

谁走了另一条路? 杰克还是比尔? 在这种情况下,使用名称“Jake”和“Bill”就像使用types名称一样。 而“他”和“他”就像使用var关键字。 在这种情况下,可能有助于更具体。 下面的例子更清晰。

杰克和比尔问好。 杰克不喜欢比尔,所以他转过头去。

在这种情况下,更明确地使句子更清楚。 但是这并不总是如此。 在某些情况下,具体使阅读变得困难。

比尔喜欢书,所以比尔去图书馆,比尔拿出一本比尔一直喜欢的书。

在这种情况下,如果我们使用“he”,并且在某些情况下将他的名字全部遗漏在一起,这相当于使用var关键字,那么读取这个句子会更容易。

比尔喜欢书,所以他去图书馆拿出一本他一直喜欢的书。

这些例子涵盖了这个要点,但是他们没有讲完整个故事。 在这些例子中,只有一种方法可以提到这个人。 要么使用他们的名字,要么使用“他”和“他”这个更加通用的术语。

在代码的情况下,我们有3种方法来帮助增加清晰度。 types,variables名称和赋值。 以这行代码为例:

 Person p = GetPerson(); 

现在的问题是,在这行代码中有足够的信息来帮助你弄清楚发生了什么?

那么下面这行代码呢? 在这种情况下你还会知道p是什么意思:

 var p = GetPerson(); 

现在怎么样:

 var p = Get(); 

或现在:

 var person = Get(); 

或者这个:

 var t = GetPerson(); 

或这个:

 var u = Person.Get(); 

关键字var是否在给定场景中起作用取决于代码的上下文,比如如何命名variables,类和方法。 这也取决于代码的复杂性和其周围的代码的其余部分。

就我个人而言,我喜欢使用var关键字,大多数时候对我来说更全面。 但是我也倾向于在这个types之后命名我的variables,所以我并没有真正地丢失任何信息。

有时候根据上下文的不同,我会做出例外,任何事情的本质都是复杂的,如果不是复杂的话,软件也不算什么。

我的规则是这样的:

  • 你是否声明了一个原始types(即bytecharstringint[]double?decimal等)? – >使用types:

     string myStr = "foo"; int[] myIntArray = [123, 456, 789]; double? myDouble = 123.3; 
  • 你是否声明了一个复杂types(即List<T>Dictionary<T, T>MyObj )? – >使用var

     var myList = List<string>(); var myDictionary = Dictionary<string, string>(); var myObjInstance = new MyObj(); 

我只想指出,在C#代码约定中,当“variables的types从赋值的右侧明显,或者当精确types不重要”时,推荐使用“var”可能为什么在ReSharper默认打开提示。 他们还提供了一些在同一文档中不会提高可读性的情况。

我看到很多正确的答案,但错过了一个完整的答案。

确实,Resharper默认情况下会过度使用var。 我想大多数人会同意这一点。 当使用var时,读取也更容易,而且types是显而易见的,例如当您使用新语句时。 我看到一篇文章,展示了如何更新检查的严重性,只显示使用var的提示。

我曾试图先评论其他post,以添加在哪里设置这些,但没有声誉。 显然,我也没有声誉发布我的屏幕截图的设置。

我将解释如何到达那里。

在Visual Studio中 – >主菜单 – > Resharper – >选项 – >代码编辑 – > C# – >代码样式 – > Var在声明中的用法

  • 对于内置types使用显式types
  • 对于简单的types显而易见的使用“var”
  • 其他地方Use'var'

在这里输入图像描述

ReSharper推荐var,因为它倾向于整理对象的创build。

比较这两个例子:

 StringBuilder bld = new StringBuilder(); var bld = new StringBuilder(); 

这只是一个简短的应该是更容易阅读。

当我用“new”显式创build新的对象时,我认为这很好。 在你的例子中,如果这些类没有正确命名,可能并不明显。

顺便说一下,R​​eSharper在“你可能想把这个build议应用到你的代码”和“你的代码坏了,要我修复它?”之间作了区分。 var关键字在build议类别中,以及类似“反转如果减less嵌套”; 你不必遵循它。

您可以通过“选项”对话框或直接通过该警报的popup菜单来configuration每个警报的烦人程度。 你可以降级varbuild议,所以他们不那么突出,或者你可以升级像'使用扩展方法'警报的东西,所以它显示为一个实际的错误。

.Net 3.0的var特性只是types推断 ,这是types安全的,并且通常会使代码更易于阅读。 但是,如果你愿意的话,你不必这样做,并且可以把这个build议关掉。

没有技术上的区别,如果你使用var,那么types是编译器隐含的。 如果你有这样的代码:

 var x = 1; 

x被暗示为一个整数,并且没有其他值可以被分配给它。

如果你改变variables的types,var关键字是有用的。 你只需要做一个改变而不是两个:

 var x = 1; --> var x = "hello"; int x = 1; --> string x = "hello"; 

var关键字是在C#3.0中引入的 – 它允许我们忘记明确指定我们的types。

你是否使用没有真正的区别

MyObject foo = DB.MyObjects.SingleOrDefault(w => w.Id == 1);

要么

var foo = DB.MyObjects.SingleOrDefault(w => w.Id == 1);

纯粹的可读性和更less的错误机会除外。

这似乎是一个陈词滥调的例子,但说以下可能有助于你的理解:

 var myInt = 23; 

返回一个inttypes,而

 var myInt = "23"; 

返回一个stringtypes。

MSDN参考

指定一个明确的对象types在某种程度上是多余的。 即使是用英文翻译,这听起来也是多余的:“将Xtypes的对象放在Xtypes的variables中”vs“将Xtypes的对象放在variables中”。

但是,使用'var'有其局限性 。 它阻止了以下纯粹美多态的使用:

假设一条狗延伸动物; 猫延伸动物类层次结构:

 Animal x = new Dog(); DoStuffWithDog(x as Dog); x = new Cat(); DoStuffWithCat(x as Cat); void DoStuffWithDog(Dog d){} void DoStuffWithCat(Cat c){} 

相同的代码,用'var'声明的x 不会被编译

 var x = new Dog(); // from this point, x is a Dog DoStuffWithDog(x as Dog); x = new Cat(); // cannot assign a Cat instance to a Dog DoStuffWithCat(x as Cat); void DoStuffWithDog(Dog d){} void DoStuffWithCat(Cat c){} 

无论如何,回到原来的问题,我不使用Resharper,但我认为这是足够聪明,以检测何时不使用'var'。 🙂

对于那些不喜欢“var”的人来说:

注意:你也可以在做“引入variables”时停止从默认的var到res。 这让我感到很沮丧,总是默认var,我每次都在改变它。

这些设置在代码编辑 – > C# – >代码样式下

在这里输入图像描述

没有技术上的区别(正如eWolf指出的那样)。 您可以使用一个或另一个,生成的CLR代码看起来是一样的。

在我看来,主要好处是这往往会迫使你使用更好的variables命名。 在你的例子中,'foo'对于一个variables名是一个相当差的select。

根据JetBrains(ReSharper的作者),他们鼓励使用默认的var。

从他们的网站 :

使用C#3.0中引入的隐式types局部variables(也称为var关键字)已经变得非常stream行,因为提高了代码的可读性。 默认情况下,ReSharper也鼓励使用var关键字,但是它的使用偏好是可以灵活configuration的。 例如,您可以select在特定情况下或在任何地方使用显式types。

在我看来,只有在定义variables的值时立即清除types是什么时才应使用var

例:

 var s = "string value"; 

很明显, s是一个string

我相信当variablestypes名称非常复杂时也是适用的。

例:

 Dictionary<SomeCustomKeyType, Dictionary<AnotherCustomKeyType, List<int>>> dict = new Dictionary<SomeCustomKeyType, Dictionary<AnotherCustomKeyType, List<int>>>(); // This is a little easier to read than the above statement var dict = Dictionary<SomeCustomKeyType, Dictionary<AnotherCustomKeyType, List<int>>>(); 

除了这些场景之外,我没有看到使用var GAIN,但是我可以想到一些可能会有害的场景:

例如,一个一次性types的右侧variables值没有清楚地显示types。 丢弃IDisposable很容易被遗忘

例:

 // returns some file writer var wr = GetWriter(); wr.add("stuff"); wr.add("more stuff"); //... //... // Now `wr` needs to be disposed, // but there is no clear indication of the type of `wr`, // so it will be easily overlooked by code writer and code reviewer. 

瓦尔是惊人的! 我遇到过许多开发人员,他们都认为var绑定了一个dynamictypes,而不是。 它仍然是静态types的,只是由编译器决定的。

以下是使用var的一些惊人的优点

例如,input var越短越容易阅读

Dictionary<int,IList<string>> postcodes = new Dictionary<int,IList<string>>() Yuk。

var postcodes = new Dictionary<int,IList<string>>() \ o / \ o /

更多的描述性variables名称 – 纤细的,但我认为它的重要性在于让var的stream动性在这里闪耀。 由于var有点模糊,它确实鼓励一个更加简单的variables名称,而不是让types自己说话。

更less的代码更改 – 如果方法调用的返回types更改。 你只需要改变方法调用,而不是每个地方使用。

匿名types – 匿名types是一个非常强大的概念,特别是在WebApi 部分资源等领域。 没有var,他们不能使用。

然而,有时候明确声明types是有用的,我发现这在基元或结构中最有用。 例如,我个人觉得这个语法非常有用:

 for(var i = 0; i < 10; i++) { } 

VS

 for(int i = 0; i < 10; i++) { } 

这完全取决于个人喜好,但使用var真的会加速你的发展,并打开一个匿名types的善良的整个世界。