C#如何向inline内联函数传递变量同时获取属性名与对应值
问题解答
结论
完全可以实现,有两种主流方案可以满足你的简化写法需求,其中C# 10+提供的语言特性可以100%匹配你期望的调用写法。
方案1:C# 10+ 原生特性支持(推荐)
利用[CallerArgumentExpression]编译时特性,编译器会自动将你传入参数的表达式文本作为键注入,运行时无额外开销,写法和你预期完全一致:
using System.Runtime.CompilerServices; void WhatIWouldLike_SetPreferences() { void f(object value, [CallerArgumentExpression(nameof(value))] string key = null) { Preferences.Set(key, value?.ToString() ?? string.Empty); } // 调用方式完全符合你的预期,无需手动传入属性名 f(Pressure); f(Temperature); }
该方案要求项目的语言版本设置为C# 10及以上,新版本Xamarin Forms、.NET MAUI项目均默认支持该特性。
方案2:表达式树兼容方案
如果你的项目暂时无法升级到C# 10,可以用表达式树实现,仅需要在调用时加lambda前缀,比原有双参数写法仍简洁很多:
using System.Linq.Expressions; void WhatIWouldLike_SetPreferences() { void f(Expression<Func<object>> expr) { MemberExpression memberExpr; // 处理值类型属性的装箱表达式 if (expr.Body is UnaryExpression unaryExpr) { memberExpr = unaryExpr.Operand as MemberExpression; } else { memberExpr = expr.Body as MemberExpression; } if (memberExpr == null) throw new ArgumentException("仅支持传入属性访问表达式"); string key = memberExpr.Member.Name; object value = expr.Compile().Invoke(); Preferences.Set(key, value?.ToString() ?? string.Empty); } // 调用方式仅需增加lambda前缀 f(() => Pressure); f(() => Temperature); }
该方案存在极少量的表达式编译开销,对于Preference这类低频IO场景完全可以忽略,不会影响运行性能。
补充说明
C#默认是值传递语义,如果你不借助上述语言特性,直接传f(Pressure)的话,方法仅能收到属性的值副本,无法获取属性对应的元信息,因此无法实现你要的效果。
内容的提问来源于stack exchange,提问作者Michael Boyd
相关产品推荐
相关产品推荐

