使用啥:var 或对象名称类型? [复制]
Posted
技术标签:
【中文标题】使用啥:var 或对象名称类型? [复制]【英文标题】:What to use: var or object name type? [duplicate]使用什么:var 或对象名称类型? [复制] 【发布时间】:2010-09-19 05:01:26 【问题描述】:这是我在编程时总是想知道的一个问题:我们在编写代码时要使用什么:
var myFiles = Directory.GetFiles(fullPath);
或
string[] myFiles = Directory.GetFiles(fullPath);
var 是新的,是一个隐式类型的局部变量,所以我们只能在本地使用,并且它有类似 can't be 这样的规则null 等,但我想知道“正常”使用它是否有任何好处。
“通常”部分表示,不是在 匿名类型、对象和集合初始化器和查询表达式中使用意图var 匿名对象,所以我的意思是......就像上面的例子一样。
你有什么想法?
【问题讨论】:
【参考方案1】:我倾向于在任何地方使用var
,但我的同事说停止,它对我们来说不太可读。所以我现在只在匿名类型、LINQ 查询以及右侧的构造函数在哪里使用var
。
【讨论】:
【参考方案2】:post 对何时使用 var 类型接口或对象类型有一些很好的指导。
【讨论】:
【参考方案3】:来自函数式编程领域,类型推断占主导地位,我尽可能为所有本地人使用var
。
在 Visual Studio 中,如果您想知道任何 local 的类型是什么,您只需将鼠标悬停在它上面即可。
【讨论】:
【参考方案4】:我认为注意到 Haskell 中通常如何处理这很有趣。感谢Curry-Howard isomorphism,可以推断出 Haskell 中任何表达式的(最一般的)类型,因此基本上不需要类型声明,除了少数例外;例如,有时您有意将类型限制为比推断出的更具体的类型。
当然,需要什么和推荐什么不是一回事;在实践中,约定似乎是***定义始终具有类型声明,而本地化定义则省略了类型声明。这似乎在整个定义的明确性和可读性之间取得了很好的平衡,与本地“帮助”或“临时”定义的简洁性形成对比。如果我理解正确,您首先不能将var
用于“***”定义(如方法或全局函数),所以我想这会转化为“在任何地方都可以使用var
”在C#世界。当然,键入“int
”的击键次数与“var
”的击键次数相同,但大多数示例会比这更长。
【讨论】:
【参考方案5】:除了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
会很有用。那是什么,而不是如何。
【讨论】:
最后一点,我有点不同意。 “什么”不是“它是什么类型”,而是“它有什么用”。我知道“var rows”声明了一个包含我的行的变量。我还需要知道什么?据推测,它表现为行的集合,所以我并不真正关心精确的类型。 我在公司开发人员的庞大代码库中看到使用它来节省一些击键并将理解负担转移给读者。我毫不怀疑任何使用这个答案的人都可以使代码更具可读性——如果他们给出了一个缝补并使用了正确的判断——但在现实世界中,懒惰的开发人员对此很满意。 只是想指出在使用var
时不需要give up
静态类型。它们是相互排斥的概念。未来访问者的快速运行... 静态与动态类型:静态在编译时检查,而动态在运行时检查。 显式与隐式类型:显式变量声明包括拼写出来的类型,而隐式变量声明意味着编译器推断出正确的类型。
大家都知道,现在MSDN 上有官方建议。它说当类型很明显时使用var
。【参考方案6】:
我个人只在两个地方使用 var:
-
使用匿名类型,即。 LINQ 相关(在某些情况下需要 var)
当语句声明并构造同一类型的特定类型时
即。这是第 2 点的示例:
var names = new List<String>();
已编辑:这是为了回应 Jon Skeet 的问题。
上面的答案实际上被简化了。基本上,我使用 var 类型是:
-
没必要知道(虽然没那么多地方)
不可能知道(LINQ,匿名类型)
以其他方式已知,或从代码中清除
在工厂方法的情况下,您在编写代码的地方只需要知道您返回的对象是某种类型的后代,并且某种类型有一个静态工厂方法,那么我会使用 var。像这样:
var connection = DatabaseConnection.CreateFromConnectionString("...");
上面的例子是我的代码中的一个真实例子。很清楚,至少对我和使用此代码的人来说,connection 是 DatabaseConnection 的后代,但既不需要理解代码,也不需要使用它。
【讨论】:
静态工厂方法怎么样,例如Foo.CreateInstance(...)? 您能否解释一下为什么要设置:var connection=...
如果_既不需要理解代码也不需要使用它的确切类型。_
这只是一个风格指南。【参考方案7】:
我尝试了“到处使用 var”的风格……这就是我没有继续使用它的原因。
-
有时会降低可读性
在 = 之后限制智能感知
键入“var”实际上并不比键入“int”、“string”等短很多,尤其是使用智能感知。
话虽如此,我仍然将它与 LINQ 一起使用。
【讨论】:
【参考方案8】:你会在这个问题上得到各种各样的意见 - 从“在任何地方使用 var”到“只在匿名类型中使用 var,你基本上必须这样做”。我喜欢Eric Lippert's take on it:
所有代码都是抽象的。是什么 代码“真的”做的是 操纵数据?不,数字?位? 不,电压?不,电子?对,但是 理解代码级别 电子是个坏主意!的艺术 编码就是弄清楚什么是正确的 抽象级别是为 观众。
在高级语言中有 总是在什么之间的这种紧张关系 代码(语义上)以及如何 代码完成它。维护 程序员需要了解两者 如果他们要去什么和怎么做 成功地做出改变。
LINQ 的重点在于它 大规模地淡化“如何”和 大量强调“什么”。经过 使用查询理解, 程序员对未来说 观众“我相信你应该 既不知道也不关心这到底是怎么回事 正在计算结果集,但您 应该非常关心什么 结果集的语义是。” 他们使代码更接近 正在实施的业务流程和 远离比特和电子 让它去吧。
隐式键入的本地人只是其中之一 你可以不强调的小方法 如何,从而强调 什么。这是否正确 在特定情况下要做的是 判断电话。所以我告诉人们 如果类型的知识是相关的 它的选择对于 该方法的持续操作, 然后不要使用隐式类型。 显式输入说“我告诉你 这是如何工作的,支付 注意”。隐式输入说“它 这是否无关紧要 事物是一个列表或一个 Customer[],重要的是它是 客户集合。”
如果类型不是相当明显,我个人倾向于使用它 - 我将 LINQ 查询包括为“相当明显”。例如,我不会为 Directory.GetFiles
这样做,因为返回 string[]
而不是(比如说)FileInfo[]
(或其他完全不同的东西)并不是很明显 - 这对你有很大的不同稍后再做。
如果在赋值运算符的右侧有一个构造函数调用,我更有可能使用var
:很明显类型是什么。这对于复杂的泛型类型特别方便,例如Dictionary<string,List<int>>
.
【讨论】:
我也是这样做的。但是,除了右侧的构造函数调用之外,如果右侧被强制转换,我也总是使用它,即末尾有一个“as MyType”。 "Electron Manipulator" 将成为我的正式功能名称:p以上是关于使用啥:var 或对象名称类型? [复制]的主要内容,如果未能解决你的问题,请参考以下文章
比较对象类型时 typeof 和 is 有啥区别? [复制]
易语言里的发送信息命令里的信息值,参数1,参数2分别是啥意思。代表啥,决定的是啥?