我最近开始使用ReSharper。
ReSharper建议将集合上的所有循环(通常是foreach
)转换为Linq
语句,即使循环包含各种条件。
- 这会提高性能吗?
- 这会使代码更易读吗?
这会提高性能吗?
一般不影响性能。使用LINQ可以提高或降低性能,但在一般情况下不是这样。
很多时候是这样的,因为它用强调迭代的目的的结构取代了强调迭代的机制的结构。这会使代码更易读吗?
强调机制:
var jacks = new List<Person>();
foreach (var person in persons)
{
if (person.Name == "Jack")
{
jacks.Add(person);
}
}
"这段代码遍历人名,每次找到一个叫Jack的人,就把他们加起来到名为"jacks"的列表
强调目的:
var jacks = persons.Where(p => p.Name == "Jack").ToList();
"把所有叫杰克的人列在一张名单上。"我们称这个列表为jacks。"
第二个版本要短得多,这也没有什么坏处,所以你的大脑可以比第一个版本更容易地一次性消化掉。
另一个例子:
var furryAnimals = furryThings.Intersect(animals).ToArray();
如果没有LINQ或者自己编写类似的代码,你绝对不可能达到这样的清晰度。这里很明显,furryAnimals
包含了同时存在于furryThings
和animals
中的任何东西。这就是你所关心的。
你不关心这些集合的交点是如何计算的。计算可能涉及一个字典作为实现细节。但是从创建字典开始的代码的另一个版本立即将您的注意力吸引到最不重要的事情上:实现细节。
一般来说,在这个问题上我应该遵循ReSharper的建议,当我不应该的时候呢?
规则总是有例外的,所以我不会在这里展示一个例外。但一般来说,我们希望代码是正确的、可维护的和快速的(通常按照这个顺序)。我将假设代码无论哪种方式都是正确的,因此无论何时您必须做出决定,都要考虑:
- 更改是否使代码更易于理解?它是否使代码在将来更容易修改?
如果你有具体的证据证明代码的速度是至关重要的,还可以考虑:
- 哪个版本运行更快?
答案因人而异。
LINQ不会自动使你的代码更快。相反的情况更可能是正确的。看看:http://geekswithblogs.net/BlackRabbitCoder/archive/2010/04/23/c-linq-vs-foreach---round-1.aspx
LINQ可以使你的代码更短。
LINQ可以使你的代码更易读。但有时LINQ也可以有非常复杂的组合,然后我选择"旧"的方式。
Resharper不考虑代码的可读性,转换成LINQ。因此,它可以生成相当复杂的表达式,比经典循环更难理解。
转换为LINQ代码本身不会改变性能,因此它更多的是代码风格偏好。
LINQ使代码更具可读性,但在大多数情况下,可读性是以性能为代价的。原因是lambas(匿名委托)是必须在内存中分配并在之后收集垃圾的类。CLR试图变得聪明,并在可能的情况下缓存委托,但不幸的是,这还不够。此外,lambda调用比简单的方法调用要慢一些。
这就是为什么ReSharper可以同时做:将代码转换为LINQ和将LINQ转换为代码。当您关心可读性时,请将所有内容转换为LINQ。当您关心性能时,为转换为LINQ设置较低的检查优先级,并在看到它时将LINQ转换为代码。通常我先用LINQ写代码,然后用ReSharper把它转换成代码。