使用内容:变量或对象名称类型

本文关键字:对象 类型 变量 | 更新日期: 2023-09-27 17:47:23

这是一个在编程时我总是想知道的问题:当我们编写代码时要使用什么:

var myFiles = Directory.GetFiles(fullPath);

string[] myFiles = Directory.GetFiles(fullPath);

var 是新的,是一个隐式类型的局部变量,所以我们只能在本地使用,它有不能为 null 等规则,但我想知道我们是否获得了"正常"使用它的任何优势。

"通常"部分说,而不是在匿名类型对象和集合初始值设定项以及查询表达式中,这是使用 var 匿名对象的意图,所以我的意思是......就像上面的例子一样。

你有什么想法?

使用内容:变量或对象名称类型

除了在 LINQ 中明显使用 var 之外,我还使用它来缩写毛茸茸的变量声明以提高可读性,例如:

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"到"只在匿名类型中使用 var,你基本上必须这样做。我喜欢Eric Lippert的看法:

所有代码都是抽象的。是什么 代码"真正"在做 操纵数据?不。数字?位? 不。电压?不。电子?是的,但是 在 电子是个坏主意!的艺术 编码是弄清楚什么是正确的 抽象级别适用于 观众。

在高级语言中,有 总是这种张力之间是什么 代码(语义上)以及如何 代码完成它。保养 程序员需要了解两者 如果他们要去什么和怎么做 成功做出改变。

LINQ 的全部意义在于它 大量淡化"如何"和 大量强调"什么"。由 使用查询理解, 程序员对未来说 观众"我相信你应该 既不知道也不关心这是怎么回事 正在计算结果集,但您 应该非常关心什么 结果集的语义是。 它们使代码更接近 正在实施的业务流程和 离比特和电子更远 让它走下去。

隐式类型的局部变量只是其中之一 你可以淡化的小方法 如何,从而强调 什么。这是否是正确的事情 在特定情况下要做的是 判断电话。所以我告诉人们 如果该类型的知识相关 它的选择对 该方法的持续操作, 然后不要使用隐式类型。 显式键入说"我告诉你 这是有原因的,请支付 注意"。隐式键入说"它 这是否无关紧要 事物是一个列表或一个 客户[],重要的是它是 一群客户。

就个人而言,如果类型不合理明显,我不倾向于使用它 - 我将 LINQ 查询包含在"相当明显"的地方。例如,我不会为Directory.GetFiles这样做,因为这返回一个string[]而不是(说)一个FileInfo[](或其他完全不同的东西)并不明显 - 这对你以后做的事情有很大的不同。

如果在赋值运算符的右侧有一个构造函数调用,我更有可能使用 var :很明显,类型是什么。这对于复杂的泛型类型特别方便,例如 Dictionary<string,List<int>> .

我个人只在两个地方使用 var:

  1. 使用匿名类型,即。与 LINQ 相关(在某些情况下需要 var)
  2. 当语句声明并构造同一类型的特定类型时

这是第 2 点的一个例子:

var names = new List<String>();

编辑:这是对Jon Skeet问题的回应。

上面的答案实际上是简化的。基本上,我使用 var,其中类型为:

  1. 没有必要知道(虽然不是那么多地方)
  2. 不可能知道(LINQ,匿名类型)
  3. 否则已知,或从代码中清除
在工厂方法

的情况下,在编写代码的地方,你需要知道的只是你返回的对象是某种类型的后代,并且某个类型具有静态工厂方法,那么我会使用 var。喜欢这个:

var connection = DatabaseConnection.CreateFromConnectionString("...");

上面的例子是我的代码中的真实示例。很明显,至少对我和使用此代码的人来说,该连接是 DatabaseConnection 的后代,但无论是理解代码还是使用它都不需要确切的类型。

我尝试了"在任何地方使用 var"风格......这就是我没有继续使用它的原因。

  1. 有时可读性下降
  2. 在 = 之后限制智能感知
  3. 键入"
  4. var"实际上并不比键入"int","string"等短多少,尤其是使用智能感知。

话虽如此,我仍然在 LINQ 中使用它。

来自函数式编程的土地,类型推断统治着一天,我尽可能为所有当地人使用var

在Visual Studio中,如果你想知道任何本地的类型是什么,你所要做的就是用鼠标悬停在它上面。

我倾向于到处使用var,但我的同事说停止,它对我们来说不太可读。所以我现在只在匿名类型、LINQ 查询和右侧构造函数 where 上使用var

这篇文章有一些关于何时使用 var 类型接口或对象类型的好指南。

我认为在

Haskell 中通常如何处理这个问题很有趣。由于 Curry-Howard 同构,可以推断出 Haskell 中任何表达式的(最通用)类型,因此除了少数例外,基本上不需要任何地方都需要类型声明;例如,有时您故意希望将类型限制为比推断更具体的内容。

当然,需要什么和推荐什么不是一回事;在实践中,约定似乎是顶级定义总是有类型声明,而本地化定义省略了类型声明。这似乎在定义作为一个整体的明确可读性与本地"帮助者"或"临时"定义的简洁可读性之间取得了良好的平衡。如果我理解正确,您首先不能将var用于"顶级"定义(如方法或全局函数),所以我想这在 C# 世界中翻译为"尽可能使用var"。当然,键入"int"与"var"的击键次数相同,但大多数示例会比这更长。