为什么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,如int
, bool
等等。
为什么这被推荐? 我不是来自计算机科学或.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议的选项 ,无论如何,
然后,在“代码检查”下,通过调整所选语言的“检查严重性”,在我的情况下,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(即
byte
,char
,string
,int[]
,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新的对象时,我认为这很好。 在你的例子中,如果这些类没有正确命名,可能并不明显。
顺便说一下,ReSharper在“你可能想把这个build议应用到你的代码”和“你的代码坏了,要我修复它?”之间作了区分。 var
关键字在build议类别中,以及类似“反转如果减less嵌套”; 你不必遵循它。
您可以通过“选项”对话框或直接通过该警报的popup菜单来configuration每个警报的烦人程度。 你可以降级var
build议,所以他们不那么突出,或者你可以升级像'使用扩展方法'警报的东西,所以它显示为一个实际的错误。
.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;
返回一个int
types,而
var myInt = "23";
返回一个string
types。
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的善良的整个世界。