What to use: var or object name type?
这是一个在编程时我总是想知道的问题:当我们编写代码时应该使用什么:
1 | var myFiles = Directory.GetFiles(fullPath); |
或
1 | string[] myFiles = Directory.GetFiles(fullPath); |
var是新的,是一个隐式类型的局部变量,所以我们只能在本地使用,它有一些规则,比如不能为空等等,但是我想知道我们是否可以"正常"使用它。
"通常"部分说,而不是在匿名类型、对象和集合初始值设定项以及查询表达式中,它们是有意使用var匿名对象的,所以我的意思是…就像上面的例子。
你有什么想法?
除了使用
1 |
总的来说,静态输入让我不愿意放弃它,这给了我一种安慰(因为我想要一个更好的单词)。我喜欢这样的感觉,当我声明一个变量时,我知道我在做什么。声明变量不仅仅是告诉编译器一些事情,它还告诉读取代码的人一些事情。
我给你举个例子。假设我有一个返回
1 | List<string> list = MyMethod(); |
很明显,对吧?事实上,这里是一个你可以很容易使用
真的。但是这个版本的代码不仅仅是声明一个变量,它还告诉我编写它的人打算做什么:
1 | IEnumerable<string> list = MyMethod(); |
编写代码的开发人员告诉我"我不会更改这个列表,也不会使用索引来访问它的成员。我要做的就是迭代它,"这是在一行代码中需要了解的大量信息。如果你使用
当然,如果你一开始不使用它,你就不会放弃它。如果您是那种编写这行代码的开发人员,那么您已经知道不会在那里使用
编辑:
我刚刚重读了乔恩·斯基特的文章,埃里克·利珀特的这句话突然出现在我面前:
Implicitly typed locals are just one small way in which you can deemphasize the how and thereby emphasize the what.
我认为,实际上在很多情况下,使用隐式类型会留下隐式的内容。不谈什么也没关系。例如,我将随意编写一个Linq查询,如下所示:
1 2 3 4 | var rows = from DataRow r in parentRow.GetChildRows(myRelation) where r.Field<bool>("Flag") orderby r.Field<int>("SortKey") select r; |
当我读到这段代码时,我认为其中一件事就是"
这是一个没有明确说明的情况。它留给我去推断。
现在,在我使用LINQ的大约90%的情况下,这一点都不重要。因为90%的时间,下一行代码是:
1 | foreach (DataRow r in rows) |
但是不难想象在代码中,将
你会对这一点有很多不同的看法——从"随处使用var"到"只使用匿名类型的var,基本上你必须这样做。"我喜欢Eric Lippert的观点:
All code is an abstraction. Is what
the code is"really" doing is
manipulating data? No. Numbers? Bits?
No. Voltages? No. Electrons? Yes, but
understanding the code at the level of
electrons is a bad idea! The art of
coding is figuring out what the right
level of abstraction is for the
audience.In a high level language there is
always this tension between WHAT the
code does (semantically) and HOW the
code accomplishes it. Maintenance
programmers need to understand both
the what and the how if they’re going
to be successful in making changes.The whole point of LINQ is that it
massively de-emphasizes the"how" and
massively emphasizes the"what". By
using a query comprehension, the
programmer is saying to the future
audience"I believe that you should
neither know nor care exactly how this
result set is being computed, but you
should care very much about what the
semantics of the resulting set are."
They make the code closer to the
business process being implemented and
farther from the bits and electrons
that make it go.Implicitly typed locals are just one
small way in which you can deemphasize
the how and thereby emphasize the
what. Whether that is the right thing
to do in a particular case is a
judgment call. So I tell people that
if knowledge of the type is relevant
and its choice is crucial to the
continued operation of the method,
then do not use implicit typing.
Explicit typing says"I am telling you
how this works for a reason, pay
attention". Implicit typing says"it
doesn’t matter a bit whether this
thing is a List or a
Customer[], what matters is that it is
a collection of customers."
就个人而言,如果类型不太明显,我就不倾向于使用它——在这里,我将LINQ查询包含为"相当明显"。例如,我不会为
如果在赋值操作符的右侧有一个构造函数调用,那么我更倾向于使用
我个人只在两个地方使用VaR:
即,这是第2点的一个例子:
1 |
编辑:这是为了回应乔恩·斯基特的问题。
上述答案实际上是简化的。基本上,我使用var,其中类型为:
在工厂方法的情况下,在编写代码的地方,您需要知道的是,您返回的对象是某个类型的后代,并且某个类型有一个静态工厂方法,那么我将使用var。如下所示:
1 | var connection = DatabaseConnection.CreateFromConnectionString("..."); |
上面的示例是我的代码中的一个真实示例。很明显,至少对我和使用此代码的人来说,连接是一个databaseconnection子代,但是无论是理解代码还是使用代码,都不需要确切的类型。
我尝试了"到处使用var"的风格…这就是为什么我没有继续使用它。
尽管如此,我还是在Linq中使用它。
我倾向于在任何地方使用
来自函数编程的领域,在那里类型推断是一天的规则,我尽可能地为所有本地人使用
在Visual Studio中,如果您想知道本地语言的类型,只需将鼠标悬停在它上面。
这篇文章在何时使用var类型接口或对象类型上有一些很好的指导方针。
我想这是有趣的注意到这通常是如何处理哈斯克尔。由于curry-howard同构,可以推断haskell中任何表达式的(最一般的)类型,因此在任何地方基本上都不需要类型声明,只有少数例外;例如,有时您故意希望将类型限制为比推断的更具体的类型。
当然,所需要的和推荐的不是同一件事;实际上,约定似乎是顶级定义总是有类型声明,而本地化定义则忽略了类型声明。这似乎在定义整体可读性的明确性与本地"助手"或"临时"定义的可读性的简洁性之间取得了良好的平衡。如果我理解正确的话,首先你不能用