Following on from last week’s introduction of the plus operator, a friend of mine challenged me to consider an alternative operator for combining validation results: &&

After a bit of experimentation, I managed to get it going - and supporting && adds some interesting capabilities that are very useful.

In C#, you can’t override the && operator directly; you instead need to separately implement three operators.

The first is & - and the implementation exactly parallels the implementation we showed last week for +:

public static ValidationResult operator &(
    ValidationResult left, ValidationResult right)
{
    if (left == null)
    {
        throw new ArgumentNullException(nameof(left));
    }

    return left.Add(right 
    ?? throw new ArgumentNullException(nameof(right)));
}

The other two operators we need to implement are true and false - and we need to decide what it means for a ValidationResult to be truthful.

I suggest that we want true to indicate that we’re able to proceed with using whatever it is that we’ve just validated. Put another way, we want false to mean that we have at least one error, and shouldn’t use the item.

The implementations are straightforward:

public static bool operator true(ValidationResult result)
    => !result.HasErrors;

public static bool operator false(ValidationResult result)
    => result.HasErrors;

The && operator does short-circuiting - if the left-hand expression is false, the right hand one isn’t evaluated at all.

Using this, we can now write elegant validation code like this:

public ValidationResult ValidateUserName()
    => UserNameIsMandatory()
       && UserNameIsUnique();

public ValidationResult UserNameIsMandatory()
    => Validation.ErrorWhen(
        string.IsNullOrEmpty(UserName),
        "Mandatory property 'UserName' not supplied.");

public ValidationResult UserNameIsUnique()
{
    // complicated database stuff
}

If no value is supplied for UserName, the error returned by UserNameIsMandatory means that nothing further happens. We only incur the cost of checking against the database if we have a UserName to check.

Nice.

Since we’ve implemented true and false as operators, we can now use the value directly in if conditions:

if (ValidateUserName())
{
    // Good to go
}

I really like the way && works, especially the short circuiting … but I’m not really sure what I think of using ValidationResult inside an if expression. What do you think? Weigh in with your thoughts, below.

Prior post in this series:
Aggregation of validation
Next post in this series:
Equality of validation

Comments

blog comments powered by Disqus