c# - 为什么ReSharper想要使用'var'来做所有事情?
我刚刚开始在Visual Studio中使用ReSharper(在关于SO的许多建议之后)。 为了试一试,我打开了一个最近的ASP.NET MVC项目。 我注意到它提出的第一个也是最常见的事情之一就是将我的大部分/全部显式声明改为int
。 例如:
//From This:
MyObject foo = DB.MyObjects.SingleOrDefault(w => w.Id == 1);
//To This:
var foo = DB.MyObjects.SingleOrDefault(w => w.Id == 1);
等等,即使是简单的类型,如int
,bool
等。
为什么要推荐这个? 我不是来自计算机科学或.NET背景,最近“陷入”.NET开发,所以我真的很想了解正在发生的事情以及它是否有益。
ReSharper建议明显过度使用var关键字。 您可以在类型明显的地方使用它:
var obj = new SomeObject();
如果类型不明显,你应该写出来:
SomeObject obj = DB.SomeClass.GetObject(42);
一个原因是提高了可读性。 哪个更好?
Dictionary<int, MyLongNamedObject> dictionary = new Dictionary<int, MyLongNamedObject>();
要么
var dictionary = new Dictionary<int, MyLongNamedObject>();
我个人更喜欢关闭这个建议。 使用var
通常可以提高可读性; 但正如您所提到的,它有时会减少它(使用简单类型,或者当结果类型模糊时)。
我喜欢选择何时使用var
以及何时不使用。 但同样,那只是我。
var
可以提高代码的可读性,同时降低对代码的即时理解。 同样,它可能会降低其他情况下代码的可读性。 有时使用它是中性的。 理解可读性的衡量标准不成比例,但取决于具体情况。 有时两者一起增加或减少。
因素是应用于var
以及目标如何支持将其数据类型立即混淆到读者,或者是否需要其类型信息来理解手头的程序部分。
例如,错误的命名可能导致var
导致代码理解的减少。 这不是var
的错:
var value1 = GetNotObviousValue(); //What's the data type?
//vs.
var value2 = Math.Abs(-3); // Obviously a numeric data type.
有时,当代码在缺少时更具可读性时,将var
用于简单数据类型是没有意义的:
var num = GetNumber(); // But what type of number?
// vs.
double num = GetNumber(); // I see, it's a double type.
有时var
可用于隐藏您不一定要注意以下复杂性的数据类型信息:
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;
如果存在匿名类型,则必须使用var
,因为没有类型名称可以通过以下方式调用它:
var o = new { Num=3, Name="" };
当您使用Visual Studio Intellisense提供类型信息(尽管有var
)时,您需要通过严格的代码读取而不需要帮助来减少对您的理解。 假设不是每个人都拥有或使用Intellisense可能是明智的。
总结基于上面的例子,我建议全权申请var
不是一个好主意,因为大多数事情最好是适度完成,并根据手头的情况如此处所示。
为什么Resharper默认使用它? 我建议放心,因为它无法解析情况的细微差别,以决定何时最好不要使用它。
在ReSharper(8.02,但可能是其他版本)中,通过首先打开ReSharper的选项菜单,可以根据您的喜好调整“使用隐式类型本地变量声明”建议的选项,无论可能是什么情况:
然后,在“代码检查”下通过调整所选语言的“检查严重性”,在我的情况下c#:
如您所见,有一些选项可以调整ReSharper所做的所有建议。 希望这能帮助像我这样已经拥有'var'使用策略的人,并希望ReSharper尊重它:)
我很惊讶没有人提到更改实例化对象的类型也更容易,因为
AVeryLongTypeName myVariable = new AVeryLongTypeName( arguments );
是一种重复的形式。 如果我想将AVeryLongTypeName
更改为其派生类之一,我只需要在使用var
时更改一次,并且仍然可以访问子类的方法。
除此之外,改进的可读性是一个重点,但正如其他人所说,var不应该被过度使用,所以我认为在Resharper中关闭提示绝对没问题。
'var'是清楚的
关于是否使用var
关键字的主要争论在于代码对您和其他开发人员的可读性。
就像你在写一个故事一样,没有明确的正确答案。 但让我们用简单的英语来看一些这方面的例子。
杰克向比尔打招呼。 他不喜欢他,所以他转过身去了另一条路。
谁走了另一条路? 杰克还是比尔? 在这种情况下,使用名称“Jake”和“Bill”就像使用类型名称。 而“他”和“他”就像使用var
关键字。 在这种情况下,它可能有助于更具体。 以下例如更清楚。
杰克向比尔打招呼。 杰克不喜欢比尔,所以他转身走了另一条路。
在这种情况下更具体地使句子更清楚。 但事情并非总是如此。 在某些情况下,具体使得阅读更难。
比尔喜欢看书,所以比尔去了图书馆,比尔拿出了比尔一直喜欢的书。
在这种情况下,如果我们使用“他”并且在某些情况下将所有名称全部遗漏,则更容易阅读该句子,这相当于使用var
关键字。
比尔喜欢书,所以他去了图书馆并拿出了他一直喜欢的书。
这些例子涵盖了要点,但它们并不能说明整个故事。 在这些例子中,只有一种方式可以引用这个人。 要么使用他们的名字,要么使用像“他”和“他”这样的更通用的术语。
在代码的情况下,我们有3种方法可以帮助增加清晰度。 类型,变量名称和赋值。 以这行代码为例:
Person p = GetPerson();
现在的问题是,在该行代码中是否有足够的信息来帮助您弄清楚发生了什么?
以下代码行怎么样? 在这种情况下,你还会知道var
的含义:
var p = GetPerson();
现在怎么样:
var p = Get();
或者现在:
var person = Get();
或者这一个:
var t = GetPerson();
或这个:
var u = Person.Get();
关键字var
在给定方案中是否有效取决于代码的上下文,例如变量,类和方法的命名方式。 它还取决于代码的复杂性以及围绕它的其余代码。
就个人而言,我喜欢使用var
关键字,大多数时候它对我来说更全面。 但我也倾向于在类型之后命名我的变量,所以我并没有真正丢失任何信息。
也就是说,有时根据上下文我做出例外情况,这就是任何复杂事物的本质,如果不复杂,软件就没有任何意义。
我也不喜欢这个。
我不希望这变成关于使用var
的辩论,它有它的用途但不应该在任何地方使用。
要记住的关键是ReSharper配置为您想要的任何编码标准。
编辑:ReSharper和var
我的规则是这样的:
您是否声明原始类型(即
byte
,char
,string
,int[]
,double?
,decimal
等)? - &GT; 使用类型:var myList = List<string>(); var myDictionary = Dictionary<string, string>(); var myObjInstance = new MyObj();
您是否声明了复杂类型(即
var myList = List<string>(); var myDictionary = Dictionary<string, string>(); var myObjInstance = new MyObj();
,Dictionary<T, T>
,MyObj
)? - &GT; 使用var
:var myList = List<string>(); var myDictionary = Dictionary<string, string>(); var myObjInstance = new MyObj();
我只想指出在C#编码约定中推荐使用“var”,当变量的类型从赋值的右侧显而易见,或者当精确类型不重要时,“ 可能是为什么默认情况下ReSharper中的提示已启用。 它们还提供了一些不会在同一文档中提高可读性的情况。
我看到很多正确的答案,但错过了完整答案。
确实,Resharper默认使用var。 我想大多数人会同意这一点。 当使用var并且类型很明显时(例如使用新语句时),它也更容易阅读。 我看到一篇文章展示了如何更新检查严重性,仅显示使用var的提示。
我曾尝试评论其他帖子,首先添加设置这些帖子但没有声誉。 显然我也没有发布我的设置截图的声誉。
我会解释如何到达那里。
在Visual Studio中 - &gt; 主菜单 - &gt; Resharper - &gt; 选项 - &gt; 代码编辑 - &gt; C# - &gt; 代码风格 - &gt; Var声明中的用法
- 对于内置类型使用显式类型
- 对于简单类型,明显时使用'var'
- 其他地方Use'var'
ReSharper推荐var,因为它倾向于整理对象创建。
比较这两个例子:
StringBuilder bld = new StringBuilder();
var bld = new StringBuilder();
这只是一个应该更容易阅读的简写。
我认为用“new”明确创建新对象时很好。 但是,在您的示例中,如果未正确命名类,则可能并不明显。
顺便说一句,ReSharper区分了“您可能希望将此建议应用于您的代码”和“您的代码已损坏,是否要我修复它?”。 var
关键字在建议类别中,以及“反转是否减少嵌套”等内容; 你不必遵循它。
您可以通过“选项”对话框配置每个警报的烦恼程度,也可以直接通过该警报的弹出菜单进行配置。 您可以降级诸如var
建议之类的内容,以便它们不那么突出,或者您可以升级诸如“使用扩展方法”警报之类的内容,以便它显示为实际错误。
.Net 3.0的var
功能只是类型推断,它是类型安全的,通常使您的代码更易于阅读。 但是你没必要,如果你愿意,可以在resharper中关闭那个推荐。
Var太神奇了! 我遇到过许多开发人员,他们认为var
绑定到动态类型,但事实并非如此。 它仍然是静态类型的,它只是由编译器决定的。
以下是使用var的一些惊人的好处
例如,更少的输入var更短且更容易阅读var
Yuk。var postcodes = new Dictionary<int,IList<string>>()
\ o / \ o /
更具描述性的变量名称 - 稀薄的一个,但我认为重要的是让var
的流动性在这里闪耀。 由于var
有点模糊,它确实鼓励一个更具有代表性的变量名称,而不是让类型说出来。
更少的代码更改 - 如果方法调用的返回类型更改。 您只需要更改方法调用,而不是每个使用它的地方。
匿名类型 - 匿名类型是一个非常强大的概念,尤其是在WebApi部分资源等领域。 没有var,就不能使用它们。
然而,有时显式声明类型是有用的,我发现这在基元或struts中最有用。 例如,我个人认为这种语法非常有用:
for(var i = 0; i < 10; i++)
{
}
VS
for(int i = 0; i < 10; i++)
{
}
这完全取决于个人偏好,但使用var
确实会加快您的开发速度并解锁整个匿名类型的善良世界。
没有技术差异,如果使用var,编译器会暗示类型。 如果您有这样的代码:
var x = 1;
x隐含为int,不能为其分配其他值。
如果更改变量的类型,var关键字很有用; 然后,您只需要进行一次更改而不是两次:
var x = 1; --> var x = "hello";
int x = 1; --> string x = "hello";
string
关键字是在C#3.0中引入的 - 它允许我们忘记明确指定我们的类型。
你是否使用没有真正的区别
string
要么
string
除了纯粹的可读性和更少的错误机会。
这似乎是一个陈词滥调的例子,但是说以下内容可能有助于您理解:
var myInt = 23;
返回string
类型,而
var myInt = "23";
返回string
类型。
MSDN参考
指定显式对象类型在某种程度上是多余的。 即使用英语翻译,它听起来也是多余的:“将X类型的对象放在X类型的变量中”vs“将X类型的对象放入变量中”。
但是,使用'var'有其局限性。 它阻止了以下对纯美的多态性的使用:
假设一只狗延伸动物; Cat扩展了Animal类层次结构:
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”的人:
注意:您还可以在执行“引入变量”时停止resharper从默认为var。 这让我很长一段时间感到沮丧,它总是默认为var,我每次都在改变它。
这些设置位于代码编辑 - &gt; C# - &gt; 代码风格
在我看来,var
只应在定义变量值时立即清楚类型是什么时使用。
例:
var s = "string value";
很明显,var
是string
。
我相信当变量类型名称非常复杂时它也是合适的。
例:
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 = new Dictionary<SomeCustomKeyType, Dictionary<AnotherCustomKeyType, List<int>>>();
除了这些场景之外,我没有看到使用var
进行任何GAIN,但我可以想到一些可能有害的场景:
例如,一种一次性类型,其右侧变量值不能清楚地显示类型。 处置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.
没有技术差异(正如电子狼指出的那样)。 您可以使用其中一个,生成的CLR代码看起来一样。
在我看来,主要的好处是,这往往会迫使你使用更好的变量命名。 在你的例子中,'foo'是变量名的一个非常糟糕的选择。
根据JetBrains(ReSharper的作者),他们鼓励默认使用var。
从他们的网站:
使用C#3.0中引入的隐式类型局部变量(也称为var关键字)已经变得非常流行,因为提高了代码的可读性。 默认情况下,ReSharper还鼓励使用var关键字,但其使用的首选项可灵活配置。 例如,您可以选择在特定情况下或在任何地方使用显式类型。
'var'为你的代码添加了一种“动态”元素(尽管代码仍然是严格键入的)。 我建议不要在类型不清楚的情况下使用它。 考虑这个例子:
var bar = GetTheObjectFromDatabase();
bar.DoSomething();
ClassA {
void DoSomething() {
//does something
}
}
ClassB {
void DoSomething() {
//does something entirely different
}
}
如果将GetTheObjectFromDatabase()的返回类型从类型A更改为B,我们将不会注意到,因为两个类都实现了DoSomething()。 然而,代码现在可能实际上做了完全不同的事情。
这可能与将不同的东西写入日志一样微妙,所以你可能不会注意到它已经太晚了。
var的以下用法应该总是很好:
var abc = new Something();