C#: 参数验证:空/空字符串

18

我不知道自己已经写了多少次代码来验证字符串参数:

public RoomName(string name)
{
    if (string.IsNullOrEmpty(name))
    {
        throw new ArgumentException("Cannot be empty", "name");
    }
}

有没有什么方法可以避免这种情况发生?是否有某些属性或设计契约机制可以避免这种情况?难道没有办法说:

public RoomName(NotNullOrEmptyString name)
{

无需实际创建该类型,如何实现?


你可能会发现这个链接关于使用属性和方法拦截进行参数验证的内容很有用。 - Joe
3个回答

7
你可以通过属性注入来实现这一点。
另一个节省编码时间,但仍然能够给你很多控制权的选择是使用类似CuttingEdge.Conditions的东西。它提供了参数检查的流畅接口,因此你可以写:
name.Requires().IsNotNull();

1

虽然这个问题已经在一段时间前得到了回答,但我最近一直在思考同样的问题。正式的代码合同(带有自动验证或检查)似乎是一个好主意,但通常它们的验证能力非常有限,对于简单的检查,如空值或空字符串检查,它们需要与老式检查一样多的代码(甚至更多)。

具有讽刺意味的是,在我的看法中,字符串情况下最好的答案确实是一个或两个类,它们包装了一个已经被检查为非null、非空或非空白的字符串,并传递这个实例:

public class NonEmptyString : IComparable<NonEmptyString>, ...
{
    private readonly string _value;

    public NonEmptyString(string value)
    {
        if (value == null)
        {
            throw new ArgumentNullException("value");
        }
        if (value.Length == 0)
        {                
            throw NewStringIsEmptyException("value");
        }
        _value = value;
    }

    public string Value
    {
        get { return _value; }
    }

    ...
}

public class NonWhiteSpaceString : NonEmptyString
{
    ....
}

当然,传递这些实例并不能避免你自己检查它们是否为空,但它具有一些重要的优点:

  • 你不必一遍又一遍地检查空字符串或空白字符,这在字符串被频繁传递的情况下可能容易出错。
  • 正如我在我的实现中所做的那样,检查null与检查空值(或空白值)是不同的,因为在前一种情况下,你希望抛出特定的ArgumentNullException,而在后一种情况下则是一些ArgumentException。
  • 它清楚地表明了字符串值的约束,就像任何包装类所应该做的那样。事实上,如果你有一个字符串有某些约束条件并且它被频繁传递,我总是建议将其封装在一个类中,以封装检查并使代码保持良好。一个很好的例子是必须满足某个正则表达式的字符串。然而,我在这里偏离了问题的本身...

1
我认为你需要在你的解决方案中添加一些参数名称的跟踪。这是因为大多数人会感到困惑,如果你使用 frob(string foo, string bar) 调用 frob(null, "a value") 并得到错误消息 System.ArgumentNullException: Value cannot be null. Parameter name: value 而不是 System.ArgumentNullException: Value cannot be null. Parameter name: foo - Conrad Frix

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接