网站文件夹命名seo,大连网站制作咨询,全球可以做外贸的社交网站,wordpress锚文本插件定义 我们把在Lambda表达式(或匿名方法)中所引用的外部变量称为捕获变量。而捕获变量的表达式就称为闭包。捕获变量 捕获的变量会在真正调用委托时“赋值”#xff0c;而不是在捕获时“赋值”#xff0c;即总是使用捕获变量的最新的值。如下代码所示#xff0c;调用委托时而不是在捕获时“赋值”即总是使用捕获变量的最新的值。如下代码所示调用委托时age的最新值为30所以输出的值也是30。int age 28;
//定义委托
Funcint, string consoleAge i $洋小豆今年{i}岁了;
age 30;
//调用委托
string outputMsg consoleAge(age);
outputMsg.Dump();输出结果如下图:捕获迭代变量 当捕获的外部变量为for循环的迭代变量时C#认为变量i是定义在循环体外的。所以当添加委托集合的for循环执行完时i的值已经变为3了因此我们在foreach中循环调用委托时i的值就都是3了。ListAction levyActions new ListAction();
for (int i 0; i 3; i)
{levyActions.Add(() i.Dump());
}
foreach (Action action in levyActions)
{action();
}输出结果如下图:那么如果我们期望输出的结果为123那需要怎么修改呢这里我们只需要在for循环内部使用局部变量即可(每次循环捕获的是不同的变量)如下修改后的代码for (int i 0; i 3; i)
{int tmp i;levyActions.Add(() tmp.Dump());
}输出结果如下图:看到这里大家应该基本明白怎么回事了吧再想下迭代除了可以使用for还可以使用foreach啊那么我们把上面示例中的for循环部分改造成foreach会怎么样呢string[] names new string[] {洋小豆, 列位一分钟, levy};
ListAction levyActions new ListAction();
foreach (string name in names)
{levyActions.Add(() name.Dump());
}输出结果如下图:纳尼输出的结果竟然跟我们上面的讲解不一样不是应该输出捕获变量的最新值吗应该输出3个“levy”啊哈哈这里是因为我的示例代码是基于.net core3.0的从C#5.0开始foreach认为循环变量都应该是“新”的变量。所以每次循环中创建委托时捕获的变量都不是同一个变量。因而输出的值肯定也就不一样了。有兴趣的童鞋可以在C#5.0之前的版本下测试下看看输出的是不是3个“levy”。背后原理 分析IL代码我们可以得知编译器在背后生成了一个私有的密封类c__DisplayClass4_0它将外部变量包装成类的成员变量而委托方法包装成类的方法。所以上述捕获for迭代变量的示例代码就可以修改成如下void Main()
{ListAction levyActions new ListAction();c__DisplayClass4_0 local new c__DisplayClass4_0();for (local.i 0; local.i 3; local.i){levyActions.Add(() local.Main_b__0());}foreach (Action action in levyActions){action();}
}private sealed class c__DisplayClass4_0
{public int i;internal void Main_b__0(){i.Dump();}
}涉及到外部变量i的地方都替换成了local.i所以每次循环修改的始终是c__DisplayClass4_0的成员变量i的值那么调用委托时输出的自然都是3了。