为什么ReSharper想要将'var'用于一切?

Chr*_*ris 207 .net c# resharper var visual-studio

我刚刚开始在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);
Run Code Online (Sandbox Code Playgroud)

等,即使采用简单的类型,如int,bool

为什么要推荐这个?我不是来自计算机科学或.NET背景,最近"陷入".NET开发,所以我真的很想了解正在发生的事情以及它是否有益.

Guf*_*ffa 281

ReSharper建议明显过度使用var关键字.您可以在类型明显的地方使用它:

var obj = new SomeObject();
Run Code Online (Sandbox Code Playgroud)

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

SomeObject obj = DB.SomeClass.GetObject(42);
Run Code Online (Sandbox Code Playgroud)

  • 为了扮演恶魔倡导者,也许如果方法或变量名称中的类型不清楚,则表明命名更多然后过度使用var的问题.我原则上同意,var只应在不清除时才使用. (35认同)
  • 在这种情况下,我宁愿使用更好的变量名.您基本上建议我们查看变量定义的位置以确定类型 - 我建议我们更好地命名变量,以便我们知道变量的目的. (32认同)
  • @Jaco:+1,但值得一提的是,建议不要将有关类型的信息放在变量名中.例如,匈牙利表示法不被认为是一种好习惯. (17认同)
  • @AnonymousType:你仍然缺少这一点.您说方法名称应始终反映方法的意图,但即使它们这样做并不意味着名称指定了返回值的类型.例如,从"Stream"对象读取的方法被命名为"Read",而不是"ReadAndReturnNumberOfBytesAsInt32". (14认同)
  • ReSharper的默认设置是否过度使用`var`是一个意见问题,而不是"明确"一件事.我不想输入编译器可以自己解决的东西.我喜欢C#类型推断,并且通常希望它与F#类型推断一样好.如果可以的话,我会从方法参数和返回类型中省略显式类型,这是F#中的标准.当然不是每个人都同意. (7认同)
  • @AnonymousType:指南不鼓励标识符中的类型名称.您是否真的建议您在RHS上的演员表中写入类型名称,以避免将其写在LHS上?那有什么好处? (6认同)
  • @AnonymousType:我认为你完全忽略了这一点.值并不总是来自方法,当它们这样做时,它可能是一个无法重命名的框架方法.您根本无法始终在结果类型明显的地方编写代码. (6认同)
  • @ nicodemus13:在任何地方阅读使用`var`的代码都很痛苦.你必须一直追踪代码,看看发生了什么.如果你真的想用它来进行重构,那么你还必须将用`var`声明的每个变量视为一个真正未知的类型,在需要任何特定类型的情况下你不能使用它.只要将变量视为特定类型,您就不再独立于该类型.更改方法的返回类型就是所谓的中断更改,并且调用代码必须更改是正常的. (5认同)
  • 我实际上[在resharper上提出了一个错误](https://youtrack.jetbrains.com/issue/RSRP-431885)关于总是推送var因为它使代码更难阅读并且与MSDN recs不一致.如果类型名称没有出现在等号的右侧,则建议不要推送它.到目前为止它已被分配但未被拒绝. (5认同)
  • +1我在这里同意.还有一些例子:`Count`属性或方法*通常会*返回一个`int`,但根据情况,没有什么可以反对返回另一个整数类型,而不会使名称混乱.返回`bool`的成员应该是一个简单的案例,但有时返回一个`bool?'可能完全没问题.使用不同的库有时意味着一次使用不同的等效类型(例如,名为`Rect`和名为`Rectangle`的东西),其中任何一个都可能被称为`Bounds`的东西返回. (2认同)
  • -1.'明确'纯粹是主观的.我持相反的观点.尽可能使用`var`避免了需要知道具体类型的拐杖.它虚拟禁止重构,因为在整个地方重新定义返回类型是一件痛苦的事.对我而言,这比虚假的"清晰度"重要得多.任何鼓励重构的东西. (2认同)
  • @ Guffa-我发现相反的情况,在我的代码周围散布着明显的类型只是让人分心,丑陋的噪音并且极大地妨碍了.我不知道如何知道显式类型确实有助于理解代码的目的是什么,我不确定读取类型定义如何帮助语义.它可能是一个突破性的变化,但它仍然更容易修复一些不再编译的地方,而不是因为没有正面理由而改变了几十个声明.不过,围绕`var`有很多意见. (2认同)

Mar*_*tta 184

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

Dictionary<int, MyLongNamedObject> dictionary = new Dictionary<int, MyLongNamedObject>();
Run Code Online (Sandbox Code Playgroud)

要么

var dictionary = new Dictionary<int, MyLongNamedObject>();
Run Code Online (Sandbox Code Playgroud)

  • 我会说第一个.更容易看到发生了什么! (252认同)
  • SO的滚动条在这里提出一点我想;) (169认同)
  • 当开发人员使用`var`来处理所有事情时我讨厌它 - 我使用TFS(基于Web的差异)进行了大量的代码审查,这使得我的工作非常困难:即`var items = GetSomeItems();`vs`IDataReader dr = GetSomeItems();`在使用`IDataReader` vs`var`时,我在两个上都缺少使用语句,但更容易捕获. (167认同)
  • 真菌:你喜欢你喜欢Redundant Text Redundant Text吗?:d (98认同)
  • 在我看来,明确是更明确的.在某些情况下,使用var会导致头痛. (68认同)
  • 如果你是一个优秀的开发人员编写好的代码,并且你正在使用像Resharper这样的库,那么你不需要知道你处理的显式类型.就像当你使用接口来声明一个契约而不是一个具体的类时,var允许你说你不关心返回"类型"是什么,你只关心它做什么,并使用命名良好的变量,使用智能和resharper/VS帮助程序(例如CTRL + CLICK导航到定义)将获得99%的方式.另外,使用var意味着如果我更改方法返回类型,则不必重写我的代码库. (15认同)
  • 我同意克里斯盖斯勒,我认为`var someNumber = 2000`是最糟糕的用途之一,因为2000在语义上是模棱两可的.是的,它将是一个int,但你可以将2000分配给一个浮点数,一个短的,一个长的等等.而`var`与`int`**保存没有输入**来启动. (9认同)
  • @Fungus:添加注释以使其绝对清楚:声明'Dictionary <int,MyLongNamedObject>'类型的'dictionary'变量 (7认同)
  • 应该注意的是[MSDN上的指南](http://msdn.microsoft.com/en-us/library/ff926074.aspx)说"当类型从右侧不明显时不要使用var"分配.",[MSDN](http://msdn.microsoft.com/en-us/library/bb384061.aspx)声明"但是,使用var确实至少有可能使你的代码更多其他开发人员很难理解.因此,C#文档通常只在需要时使用var." 作为自己的内部指导方针. (7认同)
  • @Chris,就是这样.它在编译/运行时没有区别,它是为了可读性而且(主要)用于支持匿名类型,我相信.=) (6认同)
  • var是一个隐式类型的局部变量(强类型就像你自己声明了这个类型一样) - 然而 - 编译器决定了类型 - 不是你!这意味着没有为普通可读性/冗余文本删除创建var关键字.另外 - 使用var关键字并未说明所使用的实际类型. (5认同)
  • 我只使用var,当它清楚结果类型是什么时.是的,你可以使用VS通过悬停来告诉你,但它并不是很明显.例如,我在这里使用var:`var someNumber = 2000;`但不在这里:`var items = GetSomeItems();`如下面的Guffa所述. (5认同)
  • @ORMapper - `var`的创建是为了支持LINQ和匿名类型,句点.它可以用来缩短代码并提高可读性是一个幸运的巧合. (5认同)
  • @ChrisGessler我同意这一点,并在我自己的答案中提到这个[旧的已删除问题](http://stackoverflow.com/a/633768/57477)(你需要10K +代表才能看到这个删除的问题,不幸的是 - 但我把答案的文本[这里](https://gist.github.com/anonymous/5450899)).var很棒,但是当与函数调用一起使用时返回一个非显而易见的类型时,应该使用显式类型恕我直言. (3认同)
  • 我再说一次,我返回的是什么TYPE并不重要,但是从域的角度来看这个类型代表什么,如果我遵循良好的命名约定,那么具体类型完全是多余的. (3认同)
  • 谢谢.共识似乎表明它只是一个可读性建议,而不是在编译时受益. (2认同)
  • @ user1231231412:我同意简单的类型,但是对于像`Dictionary`类型这样的复杂长类型以及用于键和内容的其他类型,它常常使明确声明变得混乱(并使我头疼)。尤其是在此示例中,当创建新对象时,无论如何都要使用new运算符指定类型。 (2认同)
  • 上面的例子`var r = new Random(); var n = r.Next();`实际上说明了`var`如何导致更可读的代码.缺乏可读性不是因为`var`,而是因为单字母变量名称.根据我的经验,`var`的使用导致开发人员从类似于编译器生成的代码的约定转向强调更好语义的约定.考虑`var rand = new Random(); var nextRand = rand.Next();`.通过使用更多的语义变量名称,代码在声明时具有清晰度,并将其保持在声明可能不可见的下游. (2认同)

Bry*_*ard 96

我个人更喜欢关闭这个建议.使用var通常可以提高可读性; 但正如您所提到的,它有时会减少它(使用简单类型,或者当结果类型模糊时).

我喜欢选择何时使用var,何时不使用.但同样,那只是我.

  • 我认为ReSharper意味着非常聪明; 难道不应该足够聪明地知道结果类型何时显而易见(例如,任何带有new关键字的东西)以及什么时候不明显? (10认同)
  • 我发现当你总是使用var(比如resharper建议)时,它会强制你正确命名你的变量. (5认同)
  • 好吧,我不知道这个特征的特殊性,但我确定知道我给它的建议量不知所措; 而且我也经常使用`var`. (3认同)

Joh*_*n K 67

var可以提高代码的可读性,同时减少对代码的即时理解.同样,它可能会降低其他情况下代码的可读性.有时使用它是中性的.理解可读性的衡量标准不成比例,但取决于具体情况.有时两者一起增加或减少.

因素是var应用于什么以及目标如何支持立即将其数据类型混淆到读者,或者需要其类型信息来理解手头的程序部分.

例如,错误的命名可能导致var代码理解的减少.这不是var故障:

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

有时,var当代码在缺少时更具可读性时,使用简单数据类型是没有意义的:

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

有时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; 
Run Code Online (Sandbox Code Playgroud)

必须使用var时,有一个匿名类型存在,因为没有类型名称通过调用它:

var o = new { Num=3, Name="" };
Run Code Online (Sandbox Code Playgroud)

当您使用Visual Studio Intellisense提供类型信息时var,您需要通过严格的代码读取而不依赖于您的理解.假设不是每个人都拥有或使用Intellisense可能是明智的.

总结基于上面的例子,我建议全权申请var不是一个好主意,因为大多数事情最好是适度完成,并根据手头的情况,如此处所示.

为什么Resharper默认使用它?我建议放心,因为它无法解析情况的细微差别,以决定何时最好不要使用它.

  • @ nicodemus13当你真正使用**返回值而不是在编写函数本身时,你通常知道何时关心函数的返回类型.您建议的命名方案可能会导致滥用,如GetResultsAsIEnumerableOfDouble,它所做的只是将您从分配左侧删除的类型信息转移到分配的右侧. (10认同)
  • 恕我直言你的例子实际上是使用`var`的好理由,它会强迫你写出不错的方法名.`GetNumber() - 但是什么类型?` - 好吧,_你为什么关心?_如果重要的是要知道,调用方法`GetNumberAsDouble()`,然后它就像你有一个返回的方法一样清晰可行string`和一个返回`double`. (5认同)

Eri*_*est 39

在ReSharper(8.02,但可能是其他版本)中,通过首先打开ReSharper的选项菜单,可以根据您的喜好调整"使用隐式类型本地变量声明"建议的选项,无论可能是什么情况:

ReSharper选项菜单

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

关闭隐式类型的局部变量建议

如您所见,有一些选项可以调整ReSharper所做的所有建议.希望这能帮助像我这样已经拥有'var'使用策略的人,并希望ReSharper尊重它:)

  • 但这对于许多在到达这里时寻找它的人来说很重要.+1 (8认同)

Phi*_*ipp 23

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

AVeryLongTypeName myVariable = new AVeryLongTypeName( arguments );
Run Code Online (Sandbox Code Playgroud)

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

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


Lui*_*rez 23

'var'是清楚的

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

就像你在写一个故事一样,没有明确的正确答案.但让我们用简单的英语来看一些这方面的例子.

杰克向比尔打招呼.他不喜欢他,所以他转过身去了另一条路.

谁走了另一条路?杰克还是比尔?在这种情况下,使用名称"Jake"和"Bill"就像使用类型名称.而"他"和"他"就像使用var关键字一样.在这种情况下,它可能有助于更具体.以下例如更清楚.

杰克向比尔打招呼.杰克不喜欢比尔,所以他转身走了另一条路.

在这种情况下更具体地使句子更清楚.但事情并非总是如此.在某些情况下,具体使得阅读更难.

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

在这种情况下,如果我们使用"他"并且在某些情况下将所有名称全部遗​​漏,则更容易阅读该句子,这相当于使用var关键字.

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

这些例子涵盖了要点,但它们并不能说明整个故事.在这些例子中,只有一种方式可以引用这个人.要么使用他们的名字,要么使用像"他"和"他"这样的更通用的术语.

在代码的情况下,我们有3种方法可以帮助增加清晰度.类型,变量名称和赋值.以这行代码为例:

Person p = GetPerson();
Run Code Online (Sandbox Code Playgroud)

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

以下代码行怎么样?p在这种情况下你还会知道什么意思:

var p = GetPerson();
Run Code Online (Sandbox Code Playgroud)

现在怎么样:

var p = Get();
Run Code Online (Sandbox Code Playgroud)

或者现在:

var person = Get();
Run Code Online (Sandbox Code Playgroud)

或者这一个:

var t = GetPerson();
Run Code Online (Sandbox Code Playgroud)

或这个:

var u = Person.Get();
Run Code Online (Sandbox Code Playgroud)

关键字var在给定方案中的作用是否很大程度上取决于代码的上下文,例如变量,类和方法的命名方式.它还取决于代码的复杂性以及围绕它的其余代码.

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

也就是说,有时根据上下文我做出例外情况,这就是任何复杂事物的本质,如果不复杂,软件就没有任何意义.


Lia*_*amB 18

我也不喜欢这个.

我不希望这变成关于使用的辩论var,它有它的用途,但不应该在任何地方使用.

要记住的关键是ReSharper配置为您想要的任何编码标准.

编辑:ReSharper和var

  • 经过一年左右的抵抗,我现在几乎总是使用var. (13认同)

小智 13

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

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

我曾尝试评论其他帖子,首先添加设置这些帖子但没有声誉.显然我也没有发布我的设置截图的声誉.

我会解释如何到达那里.

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

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

在此输入图像描述


Sum*_*ans 13

我的规则是这样的:

  • 你声明一个基本类型(即byte,char,string,int[],double?,decimal,等)? - >使用类型:

    string myStr = "foo";
    int[] myIntArray = [123, 456, 789];
    double? myDouble = 123.3;
    
    Run Code Online (Sandbox Code Playgroud)
  • 你声明的复杂类型(即List<T>,Dictionary<T, T>,MyObj)?- >使用var:

    var myList = List<string>();
    var myDictionary = Dictionary<string, string>();
    var myObjInstance = new MyObj();
    
    Run Code Online (Sandbox Code Playgroud)


jos*_*ose 12

我只想指出在C#编码约定中推荐使用"var",当变量的类型从赋值的右侧显而易见,或者当精确类型不重要时,"可能是为什么默认情况下ReSharper中的提示已启用.它们还提供了一些不会在同一文档中提高可读性的情况.


Pau*_*sik 6

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

比较这两个例子:

StringBuilder bld = new StringBuilder();

var bld = new StringBuilder();
Run Code Online (Sandbox Code Playgroud)

这只是一个应该更容易阅读的简写.

我认为用"new"明确创建新对象时很好.但是,在您的示例中,如果未正确命名类,则可能并不明显.


Tim*_*son 6

顺便说一句,ReSharper区分了"您可能希望将此建议应用于您的代码"和"您的代码已损坏,是否要我修复它?".该var关键字是建议类,与喜欢的东西"如果反转,以减少嵌套"一起; 你不必遵循它.

您可以通过"选项"对话框配置每个警报的烦恼程度,也可以直接通过该警报的弹出菜单进行配置.您可以降级var建议等内容,使其不那么突出,或者您可以升级"使用扩展方法"警报之类的内容,以便将其显示为实际错误.


Kla*_*sen 5

var.Net 3.0 的功能只是类型推断,它是类型安全的,通常使您的代码更容易阅读.但是你没必要,如果你愿意,可以在resharper中关闭那个推荐.


Kno*_*per 5

瓦尔太棒了!我遇到过很多开发人员,他们的印象是var必须使用动态类型,但事实并非如此。它仍然是静态类型,只是由编译器决定。

\n\n

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

\n\n

键入较少的var 更短且更易于阅读,例如

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

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

\n更多描述性变量名称- 脆弱的名称,但我认为让流动性var在这里闪耀很重要。虽然var有点模糊,但它确实鼓励使用更具描述性的变量名称,而不是让类型自己说话。

\n更少的代码更改- 如果方法调用的返回类型发生更改。您只需更改方法调用,而不是使用它\xe2\x80\x99s 的每个地方。

\n匿名类型- 匿名类型是一个非常强大的概念,特别是在 WebApi部分资源等领域等领域。没有 var,它们就无法使用。

\n\n

然而,有时显式声明类型很有用,我发现这在基元或结构中最有用。例如,我个人认为这种语法不是很有用:

\n\n
for(var i = 0; i < 10; i++) \n{\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

\n\n
for(int i = 0; i < 10; i++) \n{\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

这完全取决于个人喜好,但使用var真正使用将加速您的发展并解锁整个匿名类型的善良世界。

\n