ReSharper&隐式类型变量

时间:2011-07-16 10:27:41

标签: .net resharper implicit-typing

我正在使用ReSharper帮助我发现代码中可能存在的错误,虽然不是错误,但它一直抱怨我应该使用var关键字而不是在声明上显式键入变量。就我个人而言,我认为如果我写作

,对我和任何阅读我的代码的人来说都会更清楚
IList<T> someVar = new List<T>();

而不是

var someVar = new List<T>();

知道两种方式之间没有性能差异,我应该忽略这些提示还是坚持使用var关键字?

这只是一种品味问题,还是隐含地输入变量是一种好习惯?

6 个答案:

答案 0 :(得分:5)

我至少看到两个原因。

首先,问题是DRY principle:不要重复自己。如果将来您决定将变量类型从List<>更改为Stack<>LinkedList<>,那么使用var您必须在一个地方更改,否则您需要必须在两个地方改变。

两个,泛型类型声明可能很长。 Dictionary<string, Dictionary<int, List<MyObject>>>有人吗?这不适用于简单的List<T>,但是对于不同的对象类型,不应该有两种代码样式。

答案 1 :(得分:3)

这只是风格问题。我倾向于赞成var如果右侧的类型在您的示例中立即明显,但如果您不喜欢var,则禁用该规则是完全正确的。许多程序员更喜欢显式输入。

查看Eric Lippert的博客文章Uses and misuses of implicit typing,了解有关var何时合适的广泛讨论。

答案 2 :(得分:2)

主要是编码风格问题(匿名类型除外)。我个人经常在编写代码时使用var,但是在我完成时使用ReSharper的代码清理将它们转换回显式输入。这允许我更快地编写代码,但是然后将代码转换为我认为自己和其他人更可读的代码(在所有代码编写一次但多次读取之后)。

我通过关闭以下“语言机会设置”(在选项,代码检查,检查严重性中找到)来关闭使用'var'的ReSharper提示:

  

初始化程序显式声明类型时使用'var'关键字   尽可能使用'var'关键字。

您可以将ReSharper配置为在“代码清理”设置下将“var”转换为显式类型:

  

在声明中使用'var'

答案 3 :(得分:2)

我只在类型声明太长(15+个字符)时使用var。否则显式声明更具可读性。

要在Resharper 8.2中禁用它,请转到Resharper&gt;选项&gt;代码检查&gt;检查严重性&gt;语言使用机会。在搜索框中键入“使用”一词有助于过滤列表。

Reshaper screenshot

答案 4 :(得分:1)

这只是一个简洁的问题,就像自动属性一样。坚持你感觉最舒服的。

答案 5 :(得分:1)

对于初级开发人员来说,这是一个很好的问题。提问者不一定是初级的,但在向初级开发人员提供信息之前确保澄清是一件好事。

本着这种精神,无论谁发现这个问题,都应该始终明白可读性是少数几个质量属性之一,当然也是最早掌握的最重要的属性之一。可读性包括变量命名实践和显式代码,以命名一对。

也就是说,可读性的一个单独的微观方面是是否通过var关键字使用隐式类型。简短的回答是可能。带有示例的受过教育的答案可能会将可能缩小到很少

因此,为了最容易理解这一点,我将首先使用 的原因,通过var关键字使用隐含式输入。

(语言透视)不使用隐式类型的第一个原因是因为C#的主要优势在于它是强类型语言。有很多精彩的语言,其优势包括不是强类型,如Javascript。每种语言都不同,有自己的优点/缺点。对于C#来说,强类型是其最重要的优势之一。


此答案假定您的代码是SOLID。如果你是在一个遗留的代码库中工作,或者是一个没有完全专注于依赖注入或Liskov Substitution的初级开发人员,那么微调你的var用法并不是在哪里你的重点应该是现在。

只有几种方法可以分配给变量。这些是我现在想到的:

ISomething someVar = new Concrete(); // <1. Can't use var to create Interfaces.

var someVar = GetFromMethod();   // <-- 2. Taken from return type

var someVar = new MyPerson();    // <-- 3. Custom complex reference type

var someVar = new DateTime();    // <-- 4. Built-in simple Reference Type
var someVar = string.Empty;      // <--      <<

var someVar = new List<T>();     // <-- 5. Built-in complex Reference Type
var someVar = new Dictionary<string, Dictionary<int, List<MyObject>>>();

var someVar = true;              // <-- 6. simple Value type assignment

var someVar = 1;                 // <-- 7. complex Value type assignment(s)
var someVar = 1.0;               // <--      <<
var someVar = 1.0d;              // <--      <<

foreach (var i = 0; i <= . . .)  // <-- 8. Same as 7 above, but different context.

var someVar = new {Name = "yo"}; // <-- 9. Instantiate Anonymous Type

(适用击穿)

1。在上面示例的示例1中,我只说明了不能使用var关键字的唯一时间。您显然无法在Interface下创建具体的实例化。我在#5中详细介绍了如何使用Interfaces。 Don&#tt

2. 示例2假设某人正在使用与您相同的开发工具,并且每个人都希望在阅读代码时花时间来研究方法的返回类型。根据您阅读代码或代码审查的速度,这可能是一个微不足道的或一个主要的缺点。 不要在这里使用var

3. 为什么要实例化一个新的内联?正如我之前所说,这些例子假设你练习SOLID原则。这种声明变量的方式会产生代码气味。如果您在代码库中搜索new关键字,则唯一的结果应该是自动生成的代码,组合根或下面的#4。 Don 使用var 这样做

4。 new DateTime();以及其他一些罕见的内置简单类型是您应该在代码库中看到new关键字的极少数情况。在示例4中使用var关键字并不是一件大事。但说实话,你在这种情况下通过战斗来购买什么?字符串的问题相同。 可以在这里使用var ...但为什么?

5. 您应该始终尝试使用最不具体的类型。简而言之,这意味着使用小型接口。此规则主要适用于面向外部的API,因为您希望尽可能灵活地保持更改,而不会破坏消费者。这条规则的唯一原因并不是严格地应用于内部代码,因为如果开发人员想要进行重大更改,他们就有能力花费额外的时间并做额外的工作来级联破解修复程序。这不是一个很好的借口。

..... 5.1 因此,对于第一部分,请注意someVar成为Generic.List<T>类型。如果您想要创建IList类型的变量,我可以看到,那么使用var关键字并不是您想要的。这通常是声明具有最小特定类型的变量的规则。请看:IList vs List。如果您故意不允许使用变量来包含List<T>中的所有额外垃圾,该怎么办?这些规则的原因在于此。 如果您可以遵循此规则,请尝试不要使用var关键字。

..... 5.2 假设您不关心,或者不想按照建议使用接口,这很好。这也有点适用于长度的想法。如果你有嵌套的集合级别并且你的声明很长,那么没有人会责怪你使用var关键字。 好的,如果您没有使用界面

6. 这与示例#7类似,但适用于非数字值类型。简单的问题是,&#34;为什么?&#34;正如我在#4中所说,你在买什么?假设您使用默认值,则无论如何都必须指定类型。为什么要混合规则,它会买什么? 当然,但为什么?

E.G。:有时你必须明确,为什么要混合规则?:

bool isVarOkay, canUseVar;
char a, b, c, d, e, f;
bool isSample = true;
byte etc;
var isOtherSample = true; //<-- why?

7。有许多数值类型。大多数推理都是为了精确,有些是出于语义目的。无论哪种方式,为什么让编译器猜测你想要的而不是明确的。如果有时间要明确,那么数值类型就是时间。就普通的int而言,也许有一些余地可以使用var,因为它是如此直接和明显。但我宁愿保留第8点。 请勿使用var关键字

8。这个代码结构在很多地方使用,几乎可以做到这一点。但是又一次:为什么,你在节省什么? varint都是3个字符。 当然,但为什么?

9。在Anonymous返回的情况下,您几乎必须使用var关键字。不这样做会失去匿名的目的。大多数匿名类型可以内联,以便它们的结果立即转换为有用的东西,因此它们不一定必须分配给变量。但是有些事情是不值得避免的。 如有必要,请为匿名类型使用var。


<强>结论

对于匿名类型,var关键字是不可避免的。此外,对于具有多个泛型级别的泛型类型,它可以有助于长时间的声明,例如Dmitry的示例Dictionary<string, Dictionary<int, List<MyObject>>>。最后,如果您在数字4,5,6和8中显示的示例中使用var关键字,则不会伤害任何人的感受。但您不能购买任何东西。

使用var关键字允许您更改类型或允许您坚持DRY原则的想法,只不过是一个虚假的借口。只有在极少数情况下,声明的分配方正确才能表示类型应该是什么。