在Visual Studio中,ReSharper警告:"可能多次枚举IEnumerable",代码如下:
static void Main(string[] args) { IEnumerableitems = Test2(); foreach (var item in items) { Console.WriteLine(item); } var newitems = new StringBuilder(); foreach (var item in items) { newitems.Append(item); } } private static IEnumerable Test2() { string[] array1 = { "1", "2", "3" }; return array1; }
我希望Test2方法将被调用两次,但它被调用一次.
我错过了什么?
它只被调用一次因为Test2()
实际返回string []
也是一个IEnumerable
这个string []
数组仍然被引用,items
因此每次使用 items
时只需重新使用数组.
您期望的情况是Test2()
使用迭代器块的实现:
private static IEnumerableTest2() { string[] array1 = { "1", "2", "3" }; foreach (var str in array1) { yield return str; } }
看看这个例子:
void Main() { IEnumerableitems = Test2(); foreach (var item in items) { Console.WriteLine(item); } var newitems = new StringBuilder(); foreach (var item in items) { newitems.Append(item); } } IEnumerable Test2() { Console.WriteLine("Test2 called"); return GetEnum(); } IEnumerable GetEnum() { for(var i = 0; i < 5; i ++) { Console.WriteLine("Doing work..."); Thread.Sleep(50); //Download some information from a website, or from a database yield return i; } }
试想一下,return GetEnum();
是return new int[] { 1, 2, 3 }
现在,对于数组,多次迭代它们并不一定是件坏事.在你的情况下,你可以在一个循环中完成工作,但这不是resharper警告你的原因.它警告你,因为有可能Test2()
返回一个懒惰的枚举,每次迭代时它都能正常工作.
如果您运行上面的代码,您将获得此输出:
Test2 called Doing work... 0 Doing work... 1 Doing work... 2 Doing work... 3 Doing work... 4 Doing work... Doing work... Doing work... Doing work... Doing work...
请注意,Test2
它本身只被调用一次,但是枚举被迭代两次(并且工作完成了两次!).
你可以通过写:
var items = Test2().ToList();
这将立即评估可枚举并将其放入列表中.在这种情况下,工作只进行一次.