在C#中使用List的foreach和传统的for循环
在C#中使用List的foreach和传统的for循环
在C#中,我刚发现没有像C++或Java中的迭代器(iterator)。在C++中,我被告知不要使用索引迭代链表(Linked Lists),因为在每个循环中从第一个节点访问会影响性能。但在C#中似乎只有两个选择。传统的for循环(for-loop)VSforeach循环。
在C#中有什么不同吗?与C++不同,for循环没有性能问题吗?
我还听说foreach
会在每次循环迭代中创建新变量,就像Java中一样,所以我不知道哪个适合低端手机。
admin 更改状态以发布 2023年5月21日
在C#中有一个迭代器的概念,它是IEnumerable
,可以提供对集合的顺序访问。
List
和LinkedList
都实现了这个接口,在两种情况下没有与索引操作的算法复杂度相关的性能惩罚。
顺便提一下,在.NET中LinkedList
没有快速附加操作的好处,因为List
在将一个项目添加到列表末尾时具有O(1)的平摊时间,并且List
对GC的压力更小,因为它通过指数增长的数组存储进行支持,所以大多数时候您最终使用List
。
关于List
和 '同一变量'问题的性能,我认为以下代码演示了使用场景。
在“同一变量”的检查中,您可以看到对于 “for”,变量在外部范围中,在foreach
的迭代器块的最近编译器版本中,变量在内部范围中,需要检查哪个版本更改了这个。这在你制作一个闭包的情况下非常重要,而代码演示了它。
void Main() { var n = 10000000; var list = Enumerable.Range(0, n).ToList(); var array = list.ToArray(); Test(TestForeach, list, "foreach - List"); Test(TestFor, list, "for - List"); Test(TestForeach, array, "foreach - Array"); Test(TestFor, array, "for - Array"); TestSameVariableFor(); TestSameVariableForeach(); } void TestSameVariableFor() { var sum = 0; Listactions = new List (); for (var i = 0; i < 2; i++) { actions.Add(() => sum += i); } foreach (var a in actions) { a(); } Console.WriteLine("For - Sum is {0}", sum); } void TestSameVariableForeach() { var sum = 0; List actions = new List (); foreach (var i in Enumerable.Range(0, 2)) { actions.Add(() => sum += i); } foreach (var a in actions) { a(); } Console.WriteLine("Foreach - Sum is {0}", sum); } void Test(Action > action, List
list, string what) { var sw = Stopwatch.StartNew(); action(list); sw.Stop(); Console.WriteLine("Elapsed {0}, {1}", sw.ElapsedMilliseconds, what); Console.WriteLine(); } void Test(Action action, int[] list, string what) { var sw = Stopwatch.StartNew(); action(list); sw.Stop(); Console.WriteLine("Elapsed {0}, {1}", sw.ElapsedMilliseconds, what); Console.WriteLine(); } void TestFor(List list) { long sum = 0; var count = list.Count; for (var i = 0; i < count; i++) { sum += i; } Console.WriteLine(sum); } void TestForeach(List list) { long sum = 0; foreach (var i in list) { sum += i; } Console.WriteLine(sum); } void TestFor(int[] list) { long sum = 0; var count = list.Length; for (var i = 0; i < count; i++) { sum += i; } Console.WriteLine(sum); } void TestForeach(int[] list) { long sum = 0; foreach (var i in list) { sum += i; } Console.WriteLine(sum); }
输出:
49999995000000 Elapsed 37, foreach - List 49999995000000 Elapsed 6, for - List 49999995000000 Elapsed 7, foreach - Array 49999995000000 Elapsed 6, for - Array For - Sum is 4 Foreach - Sum is 1
更新:
这里是描述foreach
语义变化的帖子:
这并不能完全回答你的问题,但是还是想指出这个假设是错误的:
在C#中,我刚刚发现没有类似于C ++或Java的迭代器
在C#中,它被称为枚举器,详见IEnumerator
。
此外,考虑使用传统的for
循环的代码示例:
static void Main(string[] args) { var data = new List{ 7, 10, 0 }; for (var it = data.GetEnumerator(); it.MoveNext(); ) { Console.WriteLine(it.Current); } }
无论如何,我不认为有人会像这个示例中那样对列表或IEnumerable
进行迭代 🙂