c# - 对多个参数进行空检查并使用它们的名称抛出异常

标签 c# validation nameof

我想验证多个参数并在其中任何参数为 null 时抛出 ArgumentNullException。为了便于讨论,让我们假设我有这个:

public void DoSomething(SomeClass param1, SomeClass param2, SomeClass param3);

当然可以:

if (param1 == null)
    throw new ArgumentNullException(nameof(param1));
if (param2 == null)
    throw new ArgumentNullException(nameof(param2));
if (param3 == null)
    throw new ArgumentNullException(nameof(param3));

但它并不是特别漂亮,特别是如果它是整个应用程序中的重复检查。所以,我想我会这样做:

public static class ValidationExtensions
{
    public static void NullCheck<T>(this T subject)
    {
        if (T == null)
            throw new ArgumentNullException();
    }
}

// ...

param1.NullCheck();
param2.NullCheck();
param3.NullCheck();

但是这样我就失去了nameof。我不能做 nameof(subject) 因为那没有意义。

当然,这是一个选项:

public static class ValidationExtensions
{
    public static void NullCheck<T>(this T subject, string parameterName)
    {
        if (T == null)
            throw new ArgumentNullException(parameterName);
    }
}

// ...

param1.NullCheck(nameof(param1));
param2.NullCheck(nameof(param2));
param3.NullCheck(nameof(param3));

但它似乎很容易出错,参数重复...而且,老实说,就是不漂亮。

有什么好的方法吗?理想情况下不使用任何外部库。

最佳答案

最简洁和可维护的解决方案将是您所拥有的,或 C#7 Throw Expression

param1 = param1 ?? throw new ArgumentNullException(nameof(param1));

您可以使用表达式和一些技巧,虽然我不推荐这样做,它有味道并且隐藏了背后的简单逻辑>抽象开销。此外,它依赖于将来可能会改变的未指定行为

然而,抛开这些,我给你表达式

public static class Validator
{
   public static void Validate<T>(Expression<Func<string, T>> f)
   {
      var name = (f.Body as MemberExpression).Member.Name;
      if(f.Compile().Invoke(name) == null)
         throw new ArgumentNullException(name);    
   }
}

之所以可行,是因为编译器为 lambda 表达式(一个闭包)生成了一个类,并且局部变量变成了属性 Member.Name,这意味着它也应该可行也适用于属性(未经测试)

用法

public static void Test(string param1, string param2)
{
   Validator.Validate(x => param1);
}

public static void Main()
{
   Test(null,"asdf");
}

输出

Value cannot be null. Parameter name: param1

注意:老实说,我没有考虑太多或测试过几个用例,它可能有效也可能无效,所以我不对你用这段代码伤害的人负责

关于c# - 对多个参数进行空检查并使用它们的名称抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55013544/

相关文章:

C#:是否与 C# 的 php ctype_digit 函数类似?

c# - 在 Roslyn 中解析 nameof 表达式

c# - .net winform treeview 内存不足异常

c# - iTextSharp PdfTextExtractor GetTextFromPage 抛出 NullReferenceException

c# - 如何读取大文件并按 "\r\n"分割

php - 数据完整性和限制

c# - 在sharepoint中动态调用一个dll

ruby-on-rails - 性感验证器的唯一性与 :scope constraint

c# - 在编译时获取类的属性名称,无需对象实例化