这是一个问题,在编程时我总是想知道:在编写代码时要使用什么:
var myFiles = Directory.GetFiles(fullPath);
或
string[] myFiles = Directory.GetFiles(fullPath);
var 是新的,是一个隐式类型的局部变量,所以我们只能在本地使用,它有像不能的规则null等等,但我想知道我们是否“正常”使用它有任何好处。
“正常”部分表示,不是在匿名类型,对象和集合初始化程序和查询表达式中,而是意图使用var匿名对象,所以我的意思是......就像上面的例子一样。
你有什么想法?答案 0 :(得分:61)
除了var
与LINQ的明显使用之外,我还使用它来缩短毛状变量声明的可读性,例如:
var d = new Dictionary<string, Dictionary<string, Queue<SomeClass>>>();
一般来说,我从静态打字中得到一种安慰(因为想要一个更好的词),这让我不愿意放弃它。我喜欢当我宣布变量时我知道自己在做什么的感觉。声明一个变量并不只是告诉编译器一些东西,它告诉那些阅读你代码的人。
让我举个例子。假设我有一个返回List<string>
的方法。这段代码当然是正确的,我认为90%的C#开发人员可能会写它:
List<string> list = MyMethod();
显然,对吗?事实上,这是一个你可以轻松使用var
的地方。
真的。但这个版本的代码不只是声明一个变量,它告诉我编写它的人打算做什么:
IEnumerable<string> list = MyMethod();
编写该代码的开发人员告诉我“我不会更改此列表,也不会使用索引来访问其成员。我要做的就是迭代它。”这是在一行代码中获得的大量信息。如果您使用var
,这是您放弃的。
当然,如果你没有首先使用它,你就不会放弃它。如果您是那种编写该行代码的开发人员,那么您已经知道不会在那里使用var
。
修改:
我刚刚重读了Jon Skeet的帖子,Eric Lippert的这句话引起了我的注意:
隐式打印的本地人只是一种很小的方式,你可以在这种方式中强调如何,从而强调什么。
我认为实际上在很多情况下使用隐式类型会留下隐含的内容。没关系到什么就可以了。例如,我会随便写一个LINQ查询,如:
var rows = from DataRow r in parentRow.GetChildRows(myRelation)
where r.Field<bool>("Flag")
orderby r.Field<int>("SortKey")
select r;
当我阅读该代码时,我在阅读时所考虑的一件事是“rows
是IEnumerable<DataRow>
。”因为我知道LINQ查询返回的是IEnumerable<T>
,我可以看到正在那里选择的对象的类型。
这是没有明确的情况。我不得不推断。
现在,在我使用LINQ的大约90%的情况下,这并不重要。因为90%的时间,下一行代码是:
foreach (DataRow r in rows)
但是设想将rows
声明为IEnumerable<DataRow>
非常有用的代码并不难 - 代码中有很多不同类型的对象被查询,这是不可行的将查询声明放在迭代旁边,并且能够使用IntelliSense检查rows
是有用的。这是一件什么事,而不是一件事。
答案 1 :(得分:41)
你会对这个问题得到各种各样的意见 - 从“使用无处不在”到“只使用匿名类型的var,你基本上必须这样做”。我喜欢Eric Lippert's take on it:
所有代码都是抽象的。是什么 代码是“真正”做的 操纵数据?号码?位? 电压?电子?对,但是 理解代码级别的代码 电子是个坏主意!的艺术 编码正在弄清楚什么是正确的 抽象的水平是为了 观众。
在高级语言中有 总是这种紧张之间的关系 代码做(语义)和如何 代码完成它。保养 程序员需要了解两者 什么以及他们如何前进 成功地做出改变。
LINQ的全部意义在于它 大量不再强调“如何”和 大量强调“什么”。通过 使用查询理解, 程序员对未来说 观众“我相信你应该 既不知道也不关心这是怎么回事 正在计算结果集,但是你 应该非常关心什么 结果集的语义是。“ 他们使代码更接近 正在实施的业务流程 比特和电子更远 让它成为现实。
隐式输入的本地人只是一个 你可以不加重视的小方法 如何,从而强调 什么。这是否正确 在特定情况下做的是 判断电话。所以我告诉人们 如果类型的知识是相关的 它的选择至关重要 继续操作该方法, 然后不要使用隐式类型。 明确打字说:“我告诉你 如何工作是有原因的,付出 注意“。隐式打字说”它 这有点无关紧要 东西是List或者 客户[],重要的是它 一系列客户。“
如果类型不是很明显,我个人不会倾向使用它 - 我将LINQ查询包含为“相当明显”。例如,我不会为Directory.GetFiles
执行此操作,因为返回string[]
而不是(比方说)FileInfo[]
(或完全不同的东西)并不是很明显 - 这使得与你以后的工作有很大的不同。
如果在赋值运算符的右侧有一个构造函数调用,我更有可能使用var
:它显然是什么类型。这对于复杂的通用类型尤其方便,例如: Dictionary<string,List<int>>
。
答案 2 :(得分:11)
我个人只在两个地方使用var:
即。这是第2点的一个例子:
var names = new List<String>();
已编辑:这是对Jon Skeet提问的回应。
上述答案实际上已经简化了。基本上,我使用 var ,其中类型是:
对于工厂方法,您在编写代码的位置需要知道的是,您获取的对象是某种类型的后代,而某种类型有一个静态工厂方法,然后我会使用 var 。像这样:
var connection = DatabaseConnection.CreateFromConnectionString("...");
以上示例是我的代码中的一个真实示例。很明显,至少对我和使用此代码的人来说, connection 是一个DatabaseConnection后代,但不需要确切的类型来理解代码,也不需要使用它。
答案 3 :(得分:9)
我尝试了“随处使用var”的风格......这就是为什么我没有继续使用它。
话虽如此,我仍然将它与LINQ一起使用。
答案 4 :(得分:3)
这个post对何时使用var类型接口或对象类型有一些很好的指导。
答案 5 :(得分:3)
来自函数式编程之地,其中类型推理决定当天,我尽可能为所有本地人使用var
。
在Visual Studio中,如果您想知道任何本地的类型是什么,您只需用鼠标将鼠标悬停在它上面。
答案 6 :(得分:3)
我倾向于在任何地方使用var
,但我的同事说停止,它对我们来说不太可读。所以我现在只在匿名类型,LINQ查询和右侧构造函数的位置使用var
。
答案 7 :(得分:1)
我认为注意这通常是如何在Haskell中处理的,这很有趣。感谢Curry-Howard isomorphism,可以推断出Haskell中任何表达式的(最一般)类型,因此在任何地方都不需要类型声明,只有少数例外;例如,有时您故意将类型限制为比推断的更具体的类型。
当然,所需要的和推荐的不一样;在实践中,约定似乎是顶级定义总是具有类型声明,而本地化定义则省略了类型声明。这似乎在整个定义的可读性的明确性与本地“帮助者”或“临时”定义的可读性的简洁性之间取得了良好的平衡。如果我理解正确,您首先不能将var
用于“顶级”定义(如方法或全局函数),因此我想这会转换为“在任何地方使用var
可以“在C#世界。当然,输入“int
”与“var
”的击键次数相同,但大多数示例都会比此长。