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?

1

3 Answers 3

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();
Sign up to request clarification or add additional context in comments.

Comments

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

1 Comment

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.