更好的参数检查方式?

时间:2010-08-03 12:13:08

标签: c# parameters parameter-passing

我们将.NET 2.0框架与C#3.0一起使用(我认为这是C#的最后一个版本,它可以在2.0版本的框架上运行,如果我错了,请纠正我。)

C#内置了哪些内容可以使这种类型的参数验证更方便?

public ConnectionSettings(string url, string username, string password,
                          bool checkPermissions)
{
    if (username == null) {
        throw new ArgumentNullException("username");
    }

    if (password == null) {
        throw new ArgumentNullException("password");
    }

    if (String.IsNullOrEmpty(url)) {
        throw new ArgumentException("Must not be null or empty, it was " +
            (url == null ? url : "empty"), "url");
    }

    this.url = url;
    this.username = username;
    this.password = password;
    this.checkPermissions = checkPermissions;
}

这种参数验证成为一种常见模式,并导致许多“近似样板”代码在我们的公共方法中跋涉。

如果没有内置的东西。我们可以使用哪些很棒的免费图书馆吗?

8 个答案:

答案 0 :(得分:4)

我通常会创建静态辅助方法......

E.g。

public static void CheckNotNull(object value, string parameterName)
{
   if(value == null) { throw new ArgumentNullException(parameterName); }
}

意味着您可以将代码浓缩为类似于下面的内容,并使其更加整洁。

CheckNotNull(username, "username");
CheckNotNull(password, "password"); 

或者您可以将其作为扩展方法进行包装:

public static void CheckNotNull<T>(this T value, string parameterName)
{
   if(value == null) { throw new ArgumentNullException(parameterName); }
}

并使用如下:

username.CheckNotNull("username");
password.CheckNotNull("password");

如果你感觉真的很花哨,你可以通过反射询问参数名称。反射有点慢,所以如果你要抛出异常,你只会这样做,但它可以节省你一直输入文字参数名。

答案 1 :(得分:4)

你可以像Post Sharp一样使用il weaver,请记住编译器作为C#5中的服务将会内置这种东西。

我个人不会推荐这种方法,除非问题很严重并且必须解决。通常,如上所述,一些断言和检查前置条件是最佳实践。

EG:

public ConnectionSettings(
   [NotNullOrEmpty] string url, 
   [NotNull] string username, 
   [NotNull] string password,
   bool checkPermissions)
{
    this.url = url;
    this.username = username;
    this.password = password;
    this.checkPermissions = checkPermissions;
}

您还可以将此类内容与code contracts集成,这样您就可以执行一些丰富的静态分析。

答案 2 :(得分:3)

Here's a nice fluent way这样做。

What are your favorite extension methods for C#? (codeplex.com/extensionoverflow)

public static class Extensions
{
        public static void ThrowIfArgumentIsNull<T>(this T obj, string parameterName) where T : class
        {
                if (obj == null) throw new ArgumentNullException(parameterName + " not allowed to be null");
        }
}

internal class Test
{
        public Test(string input1)
        {
                input1.ThrowIfArgumentIsNull("input1");
        }
}

答案 3 :(得分:2)

你可以使用合同来做到这一点,但它是相同的概念。

无论如何,这应该是一种好的做法,因为它清楚地显示了公共方法的必填字段。

答案 4 :(得分:2)

它不是构建到.Net Framework中,但您可以使用Fluent Argument Validation

答案 5 :(得分:2)

与Giorgi提到的流畅的参数验证类似的想法,但是这个避免了冗余地命名参数,以及代码重构工具无法自动更新的字符串。

http://charlieflowers.wordpress.com/tag/parameter-validation/

答案 6 :(得分:1)

为了补充上面Sam的回答,这里有一个链接告诉你如何用PostSharp实现这些属性:

http://dpatrickcaldwell.blogspot.com/2009/03/validate-parameters-using-attributes.html

答案 7 :(得分:0)

我最近发布了template strings的第一个稳定版本,该库可帮助您编写如下保护条款:

>>> str(x)[-2:].zfill(2)
  • 它比您想象的要快,Guard会更深入地研究性能注意事项。
  • 您可以以扩展方法的形式添加新的验证,this document对其进行了详细说明。