我最近开始使用 ReSharper。
ReSharper 建议将集合上的所有循环(通常foreach
)转换为Linq
语句,即使循环包含各种条件。
- 这会提高性能吗?
- 这是否使代码更具可读性?
一般来说,我什么时候应该在这个问题上遵循 ReSharper 的建议,什么时候不应该?
这会提高性能吗?
一般不会影响性能。可以设计使用 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();
“把所有叫杰克的人都列在一个名单上。我们称那个名单为杰克。”
第二个版本更短也没有什么坏处,所以你的大脑可以比第一个更容易地一次性消耗它。
另一个例子:
var furryAnimals = furryThings.Intersect(animals).ToArray();
如果没有 LINQ 或编写自己的等价物,您绝对无法达到这种清晰度。在这里可以立即清楚地看到furryAnimals
包含 infurryThings
和 in 的任何内容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 使代码更具可读性,但在大多数情况下,可读性会带来性能成本。原因是 lamdbas(匿名委托)是必须在内存中分配并在之后收集垃圾的类。好吧,CLR 试图变得聪明,并在可能的情况下缓存委托,但不幸的是,这还不够。此外,lamdba 调用比简单的方法调用慢一点。
这就是为什么 ReSharper 可以做到这两点:将代码转换为 LINQ 并将 LINQ 转换为代码。当您关心可读性时,请将所有内容都转换为 LINQ。当您关心性能时,请设置低检查优先级以转换为 LINQ,并在您看到 LINQ 时将其转换为代码。通常我首先将代码编写为 LINQ,然后使用 ReSharper 将其转换为代码。真的很节省时间。