AssigningLocalFunctionstoDelegates在C#7.0中,你可以声明局部函数,即存在于另一个方法中的函数。这些局部函数可以访问周围方法的局部变量。由于局部变量仅在调用方法时存在,我想知道是否可以将局部函数分配给委托(它可以比此方法调用更长寿)。publicstaticFuncAssignLocalFunctionToDelegate(){intfactor;//局部函数intTriple(intx)=>factor*x;因子=3;返回三重;}publicstaticvoidCallTriple(){varfunc=AssignLocalFunctionToDelegate();=功能(10);控制台.WriteLine(结果);//==>30}它起作用了!我的问题是:为什么这行得通?这里发生了什么?这是有效的,因为编译器创建了一个委托来捕获闭包中的因子变量。事实上,如果您使用反编译器,您会看到生成了以下代码:publicstaticFuncAssignLocalFunctionToDelegate(){intfactor=3;返回委托(intx){返回(因子*x);};你可以看到这个因素将在闭包中被捕获。(您可能已经意识到,在幕后,编译器将生成一个类,其中包含一个包含该因子的字段。)在我的机器上,它创建了以下类作为闭包:[CompilerGenerated]privatesealedclassc__DisplayClass1_0{//Fieldspublicintfactor;//内部方法intg__Triple0(intx){return(this.factor*x);如果我将AssignLocalFunctionToDelegate()更改为publicstaticFuncAssignLocalFunctionToDelegate(){intfactor;intTriple(intx)=>因子*x;因子=3;控制台.WriteLine(三重(2));返回三重;}实现变为:publicstaticFuncAssignLocalFunctionToDelegate(){c__DisplayClass1_0CS$8__locals0;整数因子=3;控制台.WriteLine(CS$8__locals0.g__Triple0(2));返回委托(intx){返回(因子*x);};您可以看到它正在创建编译器生成的类的实例以用于Console.WriteLine()。你看不到的是它实际上分配了3来反映反编译代码的因素。要看到这一点,您必须查看IL本身(这可能是我使用的反编译器出现故障,它已经很旧了)。IL如下所示:L_0009:ldc.i4.3L_000a:stfldint32ConsoleApp3.Program/c__DisplayClass1_0::factor这是加载常量值3并将其存储在编译器生成的闭包类的factor字段中。由于局部变量只有在调用方法时才存在,所以这种说法是错误的。一旦你相信一个错误的陈述,你的整个推理链就不再有意义。“寿命不超过方法激活”不是局部变量的定义特征。局部变量的定义特征是变量的名称仅对变量的局部范围内的代码有意义。不要混淆作用域和生命周期!它们不是同一件事。Lifetime是一个运行时概念,描述了存储是如何被回收的。作用域是一个编译时概念,描述了名称如何与语言元素相关联。局部变量因其局部作用域而被称为局部变量;他们的位置完全取决于他们的名字,而不是他们的一生。出于性能或正确性的原因,可以任意延长或缩短局部变量的生命周期。在C#中,不要求局部变量只有在方法被激活时才具有生命周期。但是你已经知道了:IEnumerableNumbers(intn){for(inti=0;i如果本地人i和n的生命周期仅限于该方法,那么i和n在Numbers返回后如何仍然有值?任务FooAsync(intn){intsum=0;for(inti=0;i在第一次调用BarAsync之后,FooAsync返回任务。但不知何故,即使在FooAsync返回到callerFooAsync.FuncMakeAdder(intn){returnx=>x+n;}...varadd10=MakeAdder(10);Console.WriteLine(add10(20));即使在MakeAdder返回后,他MakeAdder.local在激活它们的方法返回后,变量可以很容易地继续存在;这在C#中一直发生。这是怎么回事?本地函数转换为委托在逻辑上与lambda没有太大区别;因为我们可以将lambda转换为委托,所以我们可以将本机方法转换为委托。另一种思考方式:假设您的代码是:returny=>Triple(y);如果您没有发现该lambda有任何问题,则只需returnTriple;而且returnTriple不会有任何问题;-同样,这两个代码片段在逻辑上是相同的操作,所以如果一个执行一个策略,另一个执行一个策略。请注意,以上并不意味着编译器团队需要将本地方法生成为带有名称的lambda。与往常一样,编译器团队可以根据本地方法的使用方式自由选择他们喜欢的任何实现策略。由于编译器团队根据lambda的具体情况,在生成lambda-to-delegate转换的策略上有许多细微的变化。例如,如果您一如既往地关心这些不同策略的性能影响,那么尝试真实场景和进行实证测量是无可替代的。以上就是《C#学习教程:委托分配局部函数》。如果对你有用,需要进一步了解《C#学习教程》,希望大家多多关注。本文收集自网络,不代表立场。如涉及侵权,请点击右边联系管理员删除。如需转载请注明出处: