我刚刚开始在Visual Studio中使用ReSharper(在SO上的许多建议之后)。为了尝试一下,我打开了一个最近的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);

等等,即使是简单的类型,如int, bool等。

为什么推荐这个?我没有计算机科学或。net背景,最近“陷入”了。net开发,所以我真的很想了解正在发生什么,以及它是否有益。


其中一个原因是可读性的提高。哪个更好?

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

or

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

没有技术上的区别,如果你使用var,类型是由编译器暗示的。如果你的代码是这样的:

var x = 1;

X被暗示为int型,不能给它赋其他值。

如果你改变变量的类型,var关键字是有用的;你只需要做一个改变,而不是两个:

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

我个人倾向于关闭这个建议。使用var通常可以提高可读性;但正如您所提到的,它有时会减少它(使用简单类型,或当结果类型不明确时)。

我更喜欢选择什么时候用var,什么时候不用。但这只是我的看法。


我也不喜欢这样。

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

要记住的关键是ReSharper被配置为你想要的任何编码标准。

编辑:ReSharper和var


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

比较这两个例子:

StringBuilder bld = new StringBuilder();

var bld = new StringBuilder();

这只是一种简写,应该更容易阅读。

我认为,当你显式地用“new”创建新对象时,这很好。然而,在您的示例中,如果类没有正确命名,可能就不那么明显了。


. net 3.0的var特性仅仅是类型推断,它是类型安全的,并且通常使您的代码更容易阅读。但你不必这么做,如果你愿意,可以在ReSharper中关闭这个建议。


ReSharper的建议显然是过度使用var关键字。你可以在类型很明显的地方使用它:

var obj = new SomeObject();

如果类型不明显,你应该写出来:

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

顺便说一句,ReSharper在“你可能想把这个建议应用到你的代码中”和“你的代码坏了,想让我修复它吗?”之间做了区分。var关键字在建议类别中,与“反转if以减少嵌套”一样;你不必遵循它。

你可以通过“选项”对话框,或者直接通过弹出菜单来设置每个警报的恼人程度。你可以降级像var建议这样的东西,让它们不那么突出,或者你可以升级像“使用扩展方法”警告这样的东西,让它显示为一个实际的错误。


var关键字是在c# 3.0中引入的——它允许我们忘记显式地指定类型。

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

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

or

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

除了纯粹的可读性和更少的出错机会。

这看起来像是一个clichéd的例子,但下面的内容可能会帮助你理解:

var myInt = 23;

返回int类型,而

var myInt = "23";

返回一个字符串类型。

MSDN参考


没有技术上的区别(正如eWolf所指出的)。你可以使用其中一种,生成的CLR代码看起来是一样的。

在我看来,主要的好处是,这往往迫使您使用更好的变量命名。在你的例子中,'foo'是一个非常糟糕的变量名。


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

AVeryLongTypeName myVariable = new AVeryLongTypeName( arguments );

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

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


指定显式对象类型在某种程度上是多余的。即使用英语翻译,它听起来也是多余的:“将X类型的对象放入X类型的变量中”vs“将X类型的对象放入变量中”。

然而,使用'var'有其局限性。它防止了以下纯美的多态用法:

假设狗伸展动物;Cat扩展了动物等级:

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可以增加代码的可读性,同时减少对代码的即时理解。同样,它也会降低代码在其他情况下的可读性。有时它的使用是中性的。可读性对理解的衡量不是成比例的,而是取决于具体情况。有时两者同时增加或减少。

这个因素是var应用于什么,以及目标对读者立即混淆其数据类型的支持程度如何,或者是否需要它的类型信息来理解手边的程序部分。

例如,不好的命名会导致var导致代码理解能力下降。这不是var的错:

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

有时,对于简单的数据类型使用var是没有意义的,因为在没有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,然后你需要更少地依赖于你的理解,通过严格的代码阅读没有帮助。假设不是每个人都拥有或使用智能感知可能是明智的。

总之,根据上面的例子,我认为全权委托var的应用不是一个好主意,因为大多数事情最好是适度地完成,并基于这里所示的手边的情况。

为什么Resharper默认使用它?为了方便起见,我建议使用它,因为它不能解析情况的细微差别来决定什么时候最好不要使用它。


我只是想指出,在c#编码约定中推荐使用“var”

当变量的类型从赋值的右边很明显时,或者当精确的类型不重要时

所以这可能是ReSharper默认开启提示的原因。它们还提供了一些在同一文档的正下方不会提高可读性的情况。


在ReSharper(8.02,但可能是其他版本)中,“使用隐式类型的局部变量声明”建议的选项可以根据您的偏好进行调整,不管它是什么,首先打开ReSharper的选项菜单:

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

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


我看到了许多正确答案,但没有完整的答案。

ReSharper确实在默认情况下过度使用var。我想大多数人都会同意这一点。当使用var并且类型很明显时(例如使用new语句时),它也更容易阅读。我看到一篇文章展示了如何更新检查的严重性,只显示使用var的提示。

我曾尝试在其他帖子上评论,添加在哪里设置这些,但没有这样的声誉。显然,我也没有名声发布我的设置截图。

我会解释怎么去那里。

在Visual Studio >主菜单> Resharper > Options > Code Editing > c# > Code Style > Var using In declarations

对于内置类型使用显式类型 对于简单类型,在明显时使用'var' 在其他地方使用'var '

ReSharper帮助文档:代码语法风格:隐式/显式类型('var'关键字) -配置使用'var'关键字的首选项


我的原则是:

你是否声明了一个基本类型(即字节,char,字符串,int[], double) ?,十进制,等等)?->类型: string myStr = "foo"; int[] myIntArray = [123, 456, 789]; 双吗?myDouble = 123.3; 您是否声明了一个复杂类型(即List<T>, Dictionary<T, T>, MyObj)?->使用var: var myList =列表<字符串>(); var myDictionary = Dictionary<string, string>(); var myObjInstance = new MyObj();


'var'表示清楚

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

就像你在写一个故事一样,没有明确的正确答案。但是让我们看一些简单英语中的例子。

杰克向比尔问好。他不喜欢他,所以转身朝另一个方向走了。

谁走了另一条路?杰克还是比尔?在本例中,使用名称“Jake”和“Bill”就像使用类型名称一样。"He"和"him"就像使用var关键字。在这种情况下,说得更具体可能会有所帮助。下面的例子就清楚多了。

杰克向比尔问好。杰克不喜欢比尔,所以他转身朝另一个方向去了。

在这种情况下,越具体句子越清晰。但情况并非总是如此。在某些情况下,说得太具体会让人更难理解。

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

在这种情况下,如果我们使用“he”,在某些情况下将他的名字一起省略,这相当于使用var关键字,将更容易阅读句子。

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

这些例子涵盖了要点,但并不能说明全部问题。在这些例子中,只有一种方式来指代这个人。要么使用他们的名字,要么使用更笼统的术语,比如“他”和“他”。

对于代码,我们有三种方法来帮助增加清晰度。类型、变量名和赋值。以这行代码为例:

Person p = GetPerson();

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

下面这行代码呢?在这种情况下,你还知道p的意思吗?

var p = GetPerson();

现在怎么样:

var p = Get();

或者现在:

var person = Get();

或者这个:

var t = GetPerson();

或:

var u = Person.Get();

关键字var在给定场景中是否有效在很大程度上取决于代码的上下文,比如变量、类和方法的命名方式。它还取决于代码的复杂性以及围绕它的其余代码。

就我个人而言,我喜欢使用var关键字,它在大多数时候对我来说更全面。但我也倾向于用类型来命名变量这样就不会丢失任何信息。

这就是说,有时我会根据上下文做出例外,这就是任何复杂事物的本质,软件如果不复杂就什么都不是。


对于那些不喜欢经常使用“var”的人,你也可以在执行“引入变量”时停止ReSharper默认使用var。这让我很长一段时间都很沮丧,它总是默认为var,而我每次都在改变它。

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


根据JetBrains (ReSharper的作者)的说法,他们鼓励在默认情况下使用var。

来自他们的网站:

使用c# 3.0引入的隐式类型局部变量(也称为var关键字)已经变得非常流行,因为它在许多场景中提高了可读性。默认情况下,ReSharper也鼓励使用var关键字,但它的使用首选项是灵活配置的-例如,你可以选择在特定情况下或任何地方使用显式类型,ReSharper将帮助你强制你的首选项。


在我看来,只有在定义变量值时立即清楚该变量的类型时才应该使用var。

例子:

var s = "string value";

很明显,s是一个字符串。

我相信当变量类型名称非常复杂时,这也是合适的。

例子:

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有任何好处,但我可以想到一些情况下它可能是有害的:

例如,一个一次性类型的右侧变量值没有清楚地显示该类型。一次性用品的处理很容易被遗忘

例子:

// 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是绑定到动态类型的,但事实并非如此。它仍然是静态类型的,只是由编译器决定。

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

Less typing var is shorter and easier to read, for instanceDictionary<int,IList<string>> postcodes = new Dictionary<int,IList<string>>() Yuk. var postcodes = new Dictionary<int,IList<string>>() \o/\o/ More descriptive variable names - tenuous one but I think its important to let the fluid nature of var shine here. As var is a bit vague, it really does encourage a more desciptive variable name rather than letting the type speak for itself. Less code changes - if the return type of a method call changes. You only have to change the method call, not every place it’s used. Anonymous types - anonymous types are a really powerful concept, especially in areas such as WebApi partial resources. Without var, they cannot be used.

然而,有时显式声明类型是有用的,我发现这在原语或结构中最有用。例如,我个人不觉得这个语法很有用:

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

}

vs

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

}

这完全取决于个人喜好,但使用var真的会加速你的开发,并打开一个匿名类型的美好世界。


'var'为你的代码添加了一种“动态”元素(尽管代码仍然是严格类型的)。我建议不要在类型不清楚的情况下使用它。想想这个例子:

var bar = GetTheObjectFromDatabase();
bar.DoSomething();

ClassA {
  void DoSomething() {
  //does something
  }
}

ClassB {
  void DoSomething() {
  //does something entirely different
  }
}

如果GetTheObjectFromDatabase()的返回类型从Type A更改为B,我们不会注意到,因为这两个类都实现了DoSomething()。然而,现在的代码实际上可能做一些完全不同的事情。

这可能就像在日志中写入不同的内容一样微妙,所以您可能不会注意到,直到为时已晚。

var的以下用法应该总是正确的:

var abc = new Something();