use*_*505 7 c# validation nameof
我想验证多个参数并抛出一个ArgumentNullException如果其中任何一个null。为了便于讨论,我们假设我有这个:
public void DoSomething(SomeClass param1, SomeClass param2, SomeClass param3);
Run Code Online (Sandbox Code Playgroud)
当然,我可以这样做:
if (param1 == null)
throw new ArgumentNullException(nameof(param1));
if (param2 == null)
throw new ArgumentNullException(nameof(param2));
if (param3 == null)
throw new ArgumentNullException(nameof(param3));
Run Code Online (Sandbox Code Playgroud)
但它并不是特别漂亮,特别是如果它是在整个应用程序中反复检查的话。所以,我想我会这样做:
public static class ValidationExtensions
{
public static void NullCheck<T>(this T subject)
{
if (T == null)
throw new ArgumentNullException();
}
}
// ...
param1.NullCheck();
param2.NullCheck();
param3.NullCheck();
Run Code Online (Sandbox Code Playgroud)
但这样我就失去了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));
Run Code Online (Sandbox Code Playgroud)
但由于参数重复,它似乎很容易出错……而且,说实话,不太漂亮。
有没有一个好的方法来做到这一点?理想情况下不使用任何外部库。
最简洁和可维护的解决方案就是您所拥有的,或者 C#7 Throw Expression
param1 = param1 ?? throw new ArgumentNullException(nameof(param1));
Run Code Online (Sandbox Code Playgroud)
您可以使用表达式和一些智能,尽管我不推荐这样做,它的味道并隐藏在抽象和开销背后的简单逻辑。此外,它依赖于未来可能发生变化的未指定行为
然而,除此之外,我给你表达
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);
}
}
Run Code Online (Sandbox Code Playgroud)
这样做的原因是因为编译器为 lambda 表达式(闭包)生成一个类,并且局部变量成为一个属性Member.Name,这意味着它也应该适用于属性(未经测试)
用法
public static void Test(string param1, string param2)
{
Validator.Validate(x => param1);
}
public static void Main()
{
Test(null,"asdf");
}
Run Code Online (Sandbox Code Playgroud)
输出
值不能为空。参数名称:param1
注意:说实话,我没有对此考虑太多,也没有对它进行超过几个用例的测试,它可能会也可能不会起作用,所以我不对你用这段代码伤害的人负责