如何在 C# 循环中捕获局部变量?
生活随笔
收集整理的這篇文章主要介紹了
如何在 C# 循环中捕获局部变量?
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
咨詢區
Morgan Cheng:
我遇到了一個有趣的問題,它的代碼大概是這樣的。
List<Func<int>>?actions?=?new?List<Func<int>>();int?variable?=?0; while?(variable?<?5) {actions.Add(()?=>?variable?*?2);++?variable; }foreach?(var?act?in?actions) {Console.WriteLine(act.Invoke()); }我的期望輸出是 0,2,4,6,8,但它最終輸出的是五個 10,看起來像是這些 action 上下文捕獲的都是同一個變量。
請問是否有變通的方法實現我要的預期結果呢?
回答區
tjlevine:
變通方法就是在你的 loop 循環體中使用一個中間變量,并將其送入到 lambda 體中,參考如下代碼:
List<Func<int>>?actions?=?new?List<Func<int>>();int?variable?=?0; while?(variable?<?5) {int?variable1?=?variable;actions.Add(()?=>?variable1?*?2);++variable; }foreach?(var?act?in?actions) {Console.WriteLine(act.Invoke()); }Console.ReadLine();Sunil:
其實這種情況在多線程下也同樣會發生,比如下面的代碼:
for?(int?counter?=?1;?counter?<=?5;?counter++) {new?Thread?(()?=>?Console.Write?(counter)).Start(); }你以為會打印出 1,2,3,4,5,最后的結果非常有趣,在我這里的輸出結果是:2,1,3,3,4 ,你那邊的結果肯定又不一樣了。
唯一的解決方案就是使用 局部變量,修改后的代碼如下:
for?(int?counter?=?1;?counter?<=?5;?counter++) {int?localVar=?counter;new?Thread?(()?=>?Console.Write?(localVar)).Start(); }點評區
可能有很多朋友不知道為什么加了一個 variable1 變量之后,代碼就正確的,要想分析,可以看 C# 生成的 IL 代碼。
private?static?void?Main(string[]?args) {List<Func<int>>?actions?=?new?List<Func<int>>();for?(int?variable?=?0;?variable?<?5;?variable++){<>c__DisplayClass0_0?<>c__DisplayClass0_?=?new?<>c__DisplayClass0_0();<>c__DisplayClass0_.variable1?=?variable;actions.Add(new?Func<int>(<>c__DisplayClass0_.<Main>b__0));}foreach?(Func<int>?act?in?actions){Console.WriteLine(act());}Console.ReadLine(); }可以清楚的看到,那個所謂的 variable1 成了匿名類 c__DisplayClass0_0 下的字段了,而且foreach循環中每次都是new的,所以這個字段必然不一樣,這也就保證了正確的結果。
總結
以上是生活随笔為你收集整理的如何在 C# 循环中捕获局部变量?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 更了吗?Windows 11 22000
- 下一篇: AgileConfig轻量级配置中心1.