【发布时间】:2026-02-25 03:00:01
【问题描述】:
我认为 ReSharper 在骗我。
我有这个扩展方法(希望)返回两个枚举的异或:
public static IEnumerable<T> Xor<T>(this IEnumerable<T> first, IEnumerable<T> second)
{
lock (first)
{
lock (second)
{
var firstAsList = first.ToList();
var secondAsList = second.ToList();
return firstAsList.Except(secondAsList).Union(secondAsList.Except(firstAsList));
}
}
}
ReSharper 认为我正在对两个参数执行 IEnumerable 的多重枚举,如您所见。如果我移除了锁,那我就很满意了。
ReSharper 是对还是错?我认为这是错误的。
edit:我确实意识到我正在多次枚举列表,但 ReSharper 说我正在多次枚举 原始参数,但我没有'认为不是真的。我将两个参数都枚举到一个列表中,这样我就可以执行实际的集合操作,但正如我所见,我实际上并没有迭代多次传递的参数。
例如,如果传递的参数实际上是查询结果,我相信这种方法不会导致集合操作执行查询风暴。我确实理解 ReSharper 警告多次枚举的含义:如果传递的枚举量很重生成,那么如果它们被枚举多次,那么对它们执行多次枚举会慢得多。
此外,移除锁肯定会让 ReSharper 更快乐:
【问题讨论】:
-
需要考虑的一点是,将代码块包装在 try/finally 块中(这就是 lock 的语法糖)使得块中的代码less可优化.如果没有 try/finally,可能会有一些可以优化的东西,或者 R# 识别为可优化的,因此不会抱怨。我建议比较两个代码块w.r.t。生成的 IL。我还建议您将问题缩小到 AakashM 详细说明的内容——您 在您的示例中枚举了两次,提供一个有警告但没有枚举两次的示例。
标签: c# resharper ienumerable