更新:这不再是 C# 6 中的问题,它引入了
nameof
操作符来解决此类场景(请参阅MSDN)。注意:参考“<a href="https://stackoverflow.com/questions/11063502/getting-names-of-local-variables-and-parameters-at-run-time-through-lambda-exp">获取在运行时通过 lambda 表达式命名局部变量(和参数)”以概括这个问题,以及一些答案。
我喜欢使用 lambda 表达式创建INotifyPropertyChanged
接口的重构安全实现的想法,使用类似于Eric De Carufel提供的代码。
我正在尝试实现类似的东西ArgumentException
,以重构安全的方式向(或其派生类)提供参数名称。
我已经定义了以下用于执行null
检查的实用方法:
public static void CheckNotNull<T>(Expression<Func<T>> parameterAccessExpression)
{
Func<T> parameterAccess = parameterAccessExpression.Compile();
T parameterValue = parameterAccess();
CheckNotNull(parameterValue, parameterAccessExpression);
}
public static void CheckNotNull<T>(T parameterValue,
Expression<Func<T>> parameterAccessExpression)
{
if (parameterValue == null)
{
Expression bodyExpression = parameterAccessExpression.Body;
MemberExpression memberExpression = bodyExpression as MemberExpression;
string parameterName = memberExpression.Member.Name;
throw new ArgumentNullException(parameterName);
}
}
然后可以使用以下语法以重构安全的方式执行参数验证:
CheckNotNull(() => arg); // most concise
CheckNotNull(arg, () => args); // equivalent, but more efficient
我的担忧在于以下几行:
Expression bodyExpression = parameterAccessExpression.Body;
MemberExpression memberExpression = bodyExpression as MemberExpression;
AMemberExpression
表示“访问字段或属性”。它保证在这种INotifyPropertyChanged
情况下正常工作,因为 lambda 表达式将是一个属性访问。
但是,在我上面的代码中,lambda 表达式在语义上是参数访问,而不是字段或属性访问。代码工作的唯一原因是 C# 编译器将匿名函数中捕获的任何局部变量(和参数)提升为后台编译器生成的类中的实例变量。Jon Skeet证实了这一点。
我的问题是:这种行为(将捕获的参数提升为实例变量)是否记录在 .NET 规范中,或者它只是一个可能在替代实现或框架的未来版本中发生变化的实现细节?具体来说,可能有parameterAccessExpression.Body is MemberExpression
返回的环境false
吗?