18

I don't know how many countless times I've had to write code to validate string arguments:

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

Is there anyway to avoid this? Is there some attribute or design-by-contract mechanism to avoid this? Is there no way to say:

public RoomName(NotNullOrEmptyString name)
{

without having to actually create that type?

core
  • 32,451
  • 45
  • 138
  • 193
  • You might find this link on [Argument validation using attributes and method interception](http://www.codinginstinct.com/2008/05/argument-validation-using-attributes.html) useful – Joe Jul 10 '09 at 00:52

3 Answers3

7

You can do that via code injection with attributes.

Another option to save some coding time, but still give you a lot of control, would be to use something like CuttingEdge.Conditions. This provides a fluent interface for argument checking, so you can write:

name.Requires().IsNotNull();
Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
1

Though the question has been answered a while ago, I have been thinking about the same problem lately. Formalized code contracts (with automatic verification or checks) seem to be a good idea, but generally, their verification-capability is quite limited, and for simple checks like null- or empty-string checking, they require just as much code (or more) than the old-fashioned checks.

Ironically, the best answer in my opinion for the string-case is indeed one or two classes that wrap a string that has been checked not to be null, empty or white-space, and pass this instance around:

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
{
    ....
}

Sure, passing around these instances does not prevent you from having to check if they are null themselves, but it's got some big advantages:

  • You don't have to check on empty or white-space strings over and over again, which can be error prone in situations where the string is passed around a lot.
  • As I have done in my implementation, checking for null is something different than checking for an empty value (or whitespace value), because you want to throw a specific ArgumentNullException in the former case, and some ArgumentException in the second.
  • It clearly signals the constraint on the value of the string, just like any wrapping class is supposed to do. In fact, if you have a string that has any constraints and it is passed around a lot, I always recommend to wrap it in a class that encapsulates the check and keeps the rest of the code out of trouble. A good example of this are strings that must satisfy a certain regular expression. However, I'm diverting from the question here...
Wim.van.Gool
  • 1,290
  • 1
  • 10
  • 19
  • 1
    I think you need to add some tracking of the parameter name to your solution. This is because most would find it confusing if you called `frob(string foo, string bar)` with `frob(null, "a value")` and got the error message `System.ArgumentNullException: Value cannot be null. Parameter name: value` instead of `System.ArgumentNullException: Value cannot be null. Parameter name: foo` – Conrad Frix Nov 08 '11 at 16:16
0

See also C#: How to Implement and use a NotNull and CanBeNull attribute for more information on Code Contracts, how they can be implemented today in VS2008, and how they will be integrated into VS2010.

Community
  • 1
  • 1
Robert Harvey
  • 178,213
  • 47
  • 333
  • 501