当前位置: 首页 > 编程语言 > C#

通过Lambda表达式在运行时获取局部变量(和参数)的名称分享

时间:2023-04-11 00:27:50 C#

在运行时通过Lambda表达式获取局部变量(和参数)的名称在运行时检索局部变量(和参数)的名称。我有以下扩展方法:publicstaticstringGetVariableName(ExpressionvariableAccessExpression){varmemberExpression=variableAccessExpression.BodyasMemberExpression;返回memberExpression.Member.Name;}...返回通过lambda表达式捕获的变量的名称:staticvoidMain(string[]args){Console.WriteLine(GetVariableName(()=>args));//输出:“args”intnum=0;Console.WriteLine(GetVariableName(()=>num));//Output:"num"}但是,这只有效,因为C#编译器将匿名函数中捕获的任何局部变量(和参数)提升为编译器在幕后生成的类中的同名实例变量(根据Jon的说法)双向飞碟)。如果不是这种情况,Body到MemberExpression将失败,因为MemberExpression表示字段或属性访问。这个变量是促销记录的行为,还是可能在其他版本的框架中改变的实现细节?注意:这个问题是我之前关于参数验证的问题的概括。更新:这不再是C#6的问题,它引入了nameof运算符来解决此类情况(请参阅MSDN)。看来我的问题的答案是否定的;该函数被非规范化。情况似乎比我原先想象的要暗淡;不仅捕获变量的泛化是非规范化的,而且将匿名函数转换为表达式树表示的整个规范也是如此。这意味着即使是一个简单的匿名函数(如下所示)也不能保证在框架的不同实现中产生一致的表达式树(直到转换标准化):Expression>add=(intx,inty)=>x+是;以下摘录自C#LanguageSpecification4.0(在所有情况下都添加了重点)。来自“4.6表达式树类型”:泛型Expression的确切定义和将匿名函数转换为表达式树类型时构造表达式树的精确规则超出了本规范的范围,并在其他地方进行了描述。来自“6.5.2评估匿名函数转换为表达式树类型”:将匿名函数转换为表达式树类型会生成表达式树(§4.6)。更准确地说,对匿名函数转换的评估会导致构造一个表示匿名函数本身结构的对象结构。表达式树的精确结构和创建它的确切过程是实现定义的。《6.5.3实现示例》中的第三个例子演示了捕获局部变量的匿名函数的改造,证实了我问题中提到的变量提升:局部变量的生命周期现在必须至少延长到匿名函数委托的生命周期。这可以通过将局部变量“提升”到编译器生成的类的字段中来实现。局部变量的实例化(第7.15.5.2节)对应于创建编译器生成类的实例,访问局部变量对应于访问编译器生成类实例中的字段。这在本节末尾得到进一步证实:在将匿名函数转换为表达式树时,也可以使用此处用于捕获局部变量的相同技术:对编译器生成的对象的引用可以存储在表达式树中,访问局部变量可以表示为对这些对象的字段访问。这种方法的优点是它允许在代理和表达式树之间共享“提升的”局部变量。但是,该部分开头有一个免责声明:此处描述的实现基于MicrosoftC#编译器使用的相同原则,但绝不是强制性的,也不是唯一可能的实现。它只是简要地提到了对表达式树的转换,因为它们的确切语义超出了本规范的范围。PSEricLippert在此评论中确认表达式树规范从未发布。在CodePlex上的DLR文档下有一个ExpressionTreesv2Spec,但它的范围似乎并不涵盖C#中匿名函数到表达式树的转换。这是您不应该依赖的行为。看看C#lambda表达式的滥用还是语法的精彩?现在阅读C#设计团队的EricLippert评论。它们包括:我刚刚询问了安德斯(以及设计团队的其他成员)他们的想法。我们只是说结果不适合家庭友好的论文,至于为什么这很糟糕,我们可以从不明显的、聪明的(记住,聪明是坏的,聪明的代码很难维护)开始,而不是全部在lambda设计器中在设想的设计用例中缓慢、脆弱、不受欢迎、不必要从这些陈述我会说它不会被记录或支持的行为。AFAIK,这是一个实现细节。但是,我认为您可以打赌它实际上不会改变。我刚刚在VS2012RC中对其进行了测试,它按预期工作-所以你至少会安全几年。以上就是C#学习教程:通过lambda表达式在运行时获取局部变量(和参数)的名称。如果对大家有用,需要了解更多C#学习教程,希望大家多加关注——本文来自网络收藏,不代表立场,如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: