如何在 C# 循环中捕获局部变量?
咨詢(xún)區(qū)
Morgan Cheng:
我遇到了一個(gè)有趣的問(wèn)題,它的代碼大概是這樣的。
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,但它最終輸出的是五個(gè) 10,看起來(lái)像是這些 action 上下文捕獲的都是同一個(gè)變量。
請(qǐng)問(wèn)是否有變通的方法實(shí)現(xiàn)我要的預(yù)期結(jié)果呢?
回答區(qū)
tjlevine:
變通方法就是在你的 loop 循環(huán)體中使用一個(gè)中間變量,并將其送入到 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:
其實(shí)這種情況在多線(xiàn)程下也同樣會(huì)發(fā)生,比如下面的代碼:
for?(int?counter?=?1;?counter?<=?5;?counter++) {new?Thread?(()?=>?Console.Write?(counter)).Start(); }你以為會(huì)打印出 1,2,3,4,5,最后的結(jié)果非常有趣,在我這里的輸出結(jié)果是:2,1,3,3,4 ,你那邊的結(jié)果肯定又不一樣了。
唯一的解決方案就是使用 局部變量,修改后的代碼如下:
for?(int?counter?=?1;?counter?<=?5;?counter++) {int?localVar=?counter;new?Thread?(()?=>?Console.Write?(localVar)).Start(); }點(diǎn)評(píng)區(qū)
可能有很多朋友不知道為什么加了一個(gè) 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(); }可以清楚的看到,那個(gè)所謂的 variable1 成了匿名類(lèi) c__DisplayClass0_0 下的字段了,而且foreach循環(huán)中每次都是new的,所以這個(gè)字段必然不一樣,這也就保證了正確的結(jié)果。
總結(jié)
以上是生活随笔為你收集整理的如何在 C# 循环中捕获局部变量?的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 更了吗?Windows 11 22000
- 下一篇: c# 按位与,按位或