重构安全 ArgumentException 的 Lambda 表达式

2023-12-22

Update:从 C# 6 开始这不再是问题,C# 6 引入了nameof https://stackoverflow.com/questions/11063502/getting-names-of-local-variables-and-parameters-at-run-time-through-lambda-exp操作员来解决此类情况(请参阅MSDN https://msdn.microsoft.com/en-us/library/dn986596.aspx).

Note: 请参阅“通过 lambda 表达式在运行时获取局部变量(和参数)的名称 https://stackoverflow.com/questions/11063502/getting-names-of-local-variables-and-parameters-at-run-time-through-lambda-exp”这个问题的概括以及一些答案。

我喜欢使用 lambda 表达式来创建重构安全实现的想法INotifyPropertyChanged接口,使用类似于提供的代码埃里克·德·卡鲁费尔 http://blog.decarufel.net/2009/07/how-to-use-inotifypropertychanged-type_22.html.

我正在尝试实现类似的方法来向ArgumentException(或其派生类)以重构安全的方式。

我定义了以下实用方法来执行null checks:

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;

A MemberExpression http://msdn.microsoft.com/en-us/library/system.linq.expressions.memberexpression.aspx表示“访问字段或属性”。它保证在INotifyPropertyChanged这种情况,因为 lambda 表达式将是属性访问。

然而,在我上面的代码中,lambda 表达式在语义上是范围访问,而不是字段或属性访问。该代码有效的唯一原因是 C# 编译器将匿名函数中捕获的任何局部变量(和参数)提升为编译器生成的类中的实例变量。这得到了证实乔恩·斯基特 https://stackoverflow.com/a/7220792/1149773.

我的问题是:这种行为(将捕获的参数提升为实例变量)是否记录在 .NET 规范中,或者它只是一个可能在框架的替代实现或未来版本中更改的实现细节?具体来说,是否存在这样的环境:parameterAccessExpression.Body is MemberExpression回报false?


闭包:正如您所说,对于参数访问,C# 编译器(是的,特别是编译器)创建一个闭包类,其中包含实例字段来存储捕获的参数变量的值。 C# 编译器的未来版本会改变这种情况吗?当然。也许在 C# 的未来版本中,生成的闭包类将具有随机命名的变量,因为名称在运行时并不重要。此外,您拥有的代码可能不适用于其他 .NET 语言。您会注意到,VB .NET 生成的表达式树和闭包类有时与 C# 略有不同......

我不确定您当前的实现是否适用于结构(尽管我可能记错了......我正在考虑处理拳击的情况可能只适用于Expression<Func<T, object>>(阅读后请自行尝试)。

无论如何...所有这些都说了...它会在 C# 的未来版本中改变吗?可能不会。如果确实如此,您可以更改内部实现来处理它可能......

至于性能:请务必小心。您已经说过传递两个参数会更有效,因此您不需要编译和评估 lambda...但要清楚的是,您每次编译时都会在此处讨论 15 到 30 毫秒,并且评价。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

重构安全 ArgumentException 的 Lambda 表达式 的相关文章

随机推荐

  • 带表情符号的 Android 键盘

    所以我想在我的应用程序中拥有一个带有表情符号的键盘 就像 Whatsapp 或 Hangouts 一样 我怎样才能做到这一点 我想保留我的键盘 我只想添加选项卡来放置表情符号 我认为软键盘很容易支持它 但到目前为止我什么也没找到 任何人都可
  • gevent 在 Ubuntu 上无法正确安装

    我想尝试一下gevent http gevent org 但是安装后我无法加载任何 gevent 模块 安装步骤为 sudo apt get install libevent dev sudo pip install greenlet su
  • Django REST Framework:“BasePermissionMetaclass”对象不可迭代

    Python Django n00b 从 javascript 转移过来 尝试使用 Django REST Framework 添加 API 端点 我希望最终能够使用 PATCH 请求的正文更新用户 但现在我只希望它不要抛出 500 错误
  • Django、uWSGI 和 nginx:进程“无故”死亡

    我正在使用 uWSGI 和 nginx 运行两个并行的 Django 应用程序 其中一个负载稍大一些 两者都非常小 大约每 24 小时就会死机一次 并显示以下消息 pid 16358 app 0 req 1000 1000 127 0 0
  • 使用 Webpack 替换/别名文件

    我正在尝试在我的项目中使用一个非常新的第三方模块 我使用它安装了npm 该模块显然是在具有不区分大小写文件系统的操作系统上开发的 因此它需要一个文件injectable js而实际的文件名是Injectable js 这会破坏捆绑过程 该模
  • angular2 router.navigate 内部 auth0 回调

    在 auth0lock 的回调中调用 router navigate 后 我在渲染模板时遇到问题 登录组件 ts import Component Inject from angular2 core import Router Compon
  • 如何冻结表格报告中的第一列?

    我有一个包含 70 列的表格报告 我的要求是在水平滚动时冻结第一列 我已尝试检查 Tablix 属性中的行标题 但仍然不起作用 如何冻结第一列 以下是在 SSRS 中冻结列 行的步骤 步骤1 去Groupings窗格底部并选择高级模式 步骤
  • 单线程执行任务,无需排队进一步的请求

    我需要异步执行任务 同时丢弃任何进一步的请求 直到任务完成 同步方法只是将任务排队并且不会跳过 我最初想使用 SingleThreadExecutor 但它也会对任务进行排队 然后 我查看了 ThreadPoolExecutor 但它读取队
  • 阻止访问 JavaScript 文件

    假设我有一个 JavaScript 文件 使用 htaccess 有没有办法让用户无法查看 JavaScript 文件内部 RewriteEngine on RewriteCond HTTP REFERER http your domain
  • Hibernate 3.5.x:NoSuchMethodError:javax.persistence.OneToMany.orphanRemoval

    我正在尝试升级到 Hibernate 3 5 3 FINAL 运行单元测试时 我现在收到以下异常 java lang NoSuchMethodError javax persistence OneToMany orphanRemoval Z
  • java中如何将json字符串放入列表中

    我得到了一个JSON array像字符串一样 id ca Primary Diagnosis Dt field ca Primary Diagnosis Dt type date input text operator not equal
  • 用户控件中的 INotifyPropertyChanged

    我有一个从 TextBox 控件继承的自定义控件 我想实施INotifyPropertyChanged我的自定义控件中的界面 public class CustomTextBox TextBox INotifyPropertyChanged
  • 我应该在 Java Web 应用程序中使用安全管理器吗?

    使用运行应用程序服务器进程的用户的权限来保护 Java Web 应用程序是否足够 或者将 SecurityManager 与合适的策略文件一起使用是否合理 我曾经做过前者 而不是后者 但一些客户希望我们也使用 SecurityManager
  • 在 Xamarin Android 中启用 Multi-Dex 后出错

    在创建 Xamarin Android 应用程序时 添加对 Infragistics Chart 控件和 Google Play 服务的引用后 我们必须启用 启用 Multi Dex 属性true 因为应用程序达到了 65K 的 dex 方
  • AngularJS:避免使用 $location 进行 url 编码

    我注意到 当我将一个数组参数传递给 location search 时 它的编码如下例所示 location path somePath search ids 1 2 3 becomes somePath ds 5B 5D 1 ds 5B
  • CNCopyCurrentNetworkInfo() 返回错误数据

    Apple 在 OS 4 1 中引入了 CNCopyCurrentNetworkInfo 函数 https developer apple com library ios documentation SystemConfiguration
  • Rails 中的匹配和路线

    我生成了一个控制器并更改了路线 但打开链接会在我的本地服务器上产生错误 生成控制器和路线 rails generate controller StaticPages home about team contact 更改路线 rb MyApp
  • 如何在 ssrs 的 IIF 表达式中使用多个条件(使用 AND)

    我想隐藏 SSRS 报告中数量为零的行 有期初库存 总发货 转出 销售数量 库存调整 期末库存等多个数量栏 我正在使用以下表达式来完成此任务 IIF Fields OpeningStock Value 0 AND Fields GrossD
  • 如何使用 Ruby 一步初始化一个数组?

    我这样初始化一个数组 array Array new array lt lt 1 lt lt 2 lt lt 3 是否可以一步完成 如果是这样 怎么办 您可以使用数组文字 array 1 2 3 您还可以使用范围 array 1 3 to
  • 重构安全 ArgumentException 的 Lambda 表达式

    Update 从 C 6 开始这不再是问题 C 6 引入了nameof https stackoverflow com questions 11063502 getting names of local variables and para