ReSharper 2025.2 Help

代码检查:可能的多次枚举

请参考以下代码片段:

IEnumerable<string> names = GetNames(); foreach (var name in names) Console.WriteLine("Found " + name); var allNames = new StringBuilder(); foreach (var name in names) allNames.Append(name + " ");

假设 GetNames() 返回一个 IEnumerable<string> ,我们实际上通过在两个 foreach 语句中枚举此集合两次而做了额外的工作。

如果 GetNames() 导致数据库查询,情况可能会变得更糟,在这种情况下,如果在两次调用之间某些其他进程更改了数据库,您可能会在两个 foreach 循环中获得不同的值。

这种问题可以很容易地解决——通过将序列转换为数组或列表来强制在变量初始化时进行枚举,例如:

List<string> names = GetNames().ToList();

您的其余代码可以保持不变,因为数组和列表类型都实现了 IEnumerable 接口。

误报

有时,如果 IEnumerable 对象在被枚举之前被传递给某个方法,此检查可能会产生误报。 例如:

public void Foo(IEnumerable<string> values) { ThrowIfNull(values, nameof(values)); var x = values.ToList(); // Possible multiple enumeration of IEnumerable } public static void ThrowIfNull<T>(T value, string name) where T : class { // custom check for null but no enumeration }

在这种情况下,ReSharper 假定该方法会进行额外的枚举,这在大多数情况下是正确的。 如果该方法实际上并未枚举 IEnumerable 对象,您可以使用 [NoEnumerationAttribute]标记相应的参数以防止误报:

public void Foo(IEnumerable<string> values) { ThrowIfNull(values, nameof(values)); var x = values.ToList(); // No warnings about multiple enumeration } public static void ThrowIfNull<T>([NoEnumeration] T value, string name) where T : class { // custom check for null but no enumeration }
最后修改日期: 2025年 9月 27日