Simplifying Parameter Null and Other Checks with the GuardClauses Library

Often you want to add null checking and other check code at the start of a method to ensure all the values passed into the method are valid before continuing.

For example the following method checks the name and age:

public static void AddNewPerson(string name, int ageInYears)
{
    if (string.IsNullOrWhiteSpace(name))
    {
        throw new ArgumentException($"Cannot be null, empty, or contain only whitespace.", nameof(name));
    }

    if (ageInYears < 1)
    {
        throw new ArgumentOutOfRangeException(nameof(ageInYears), "Must be greater than zero.");
    }

    // Add to database etc.
}

This “guard” kind of code can “clutter” the method and reduce readability.

One library I recently came across is the Guard Clauses library from Steve Smith.

Once this library is installed we could refactor the preceding code to look like the following:

public static void AddNewPerson(string name, int ageInYears)
{
    Guard.Against.NullOrWhiteSpace(name, nameof(name));
    Guard.Against.NegativeOrZero(ageInYears, nameof(ageInYears));

    // Add to database etc.
}

Passing a null name results in the exception: System.ArgumentNullException: Value cannot be null. (Parameter 'name')

Passing an empty string results in: System.ArgumentException: Required input name was empty. (Parameter 'name')

Passing in an age of zero results in: System.ArgumentException: Required input ageInYears cannot be zero or negative. (Parameter 'ageInYears')

The code is also more readable and succinct.

Out of the box the library comes with the following guards (taken from the documentation):

  • Guard.Against.Null (throws if input is null)
  • Guard.Against.NullOrEmpty (throws if string or array input is null or empty)
  • Guard.Against.NullOrWhiteSpace (throws if string input is null, empty or whitespace)
  • Guard.Against.OutOfRange (throws if integer/DateTime/enum input is outside a provided range)
  • Guard.Against.OutOfSQLDateRange (throws if DateTime input is outside the valid range of SQL Server DateTime values)
  • Guard.Against.Zero (throws if number input is zero)

You can also define your own reusable clauses:

// Define in this namespace so can use alongside built-in guards with no additional namespaces required
namespace Ardalis.GuardClauses
{
    public static class PositiveGuard
    {
        public static void Positive(this IGuardClause guardClause, int input, string parameterName)
        {
            if (input >= 0)
            {
                throw new ArgumentOutOfRangeException(parameterName, $"Required input {parameterName} cannot be positive.");
            }                           
        }
    }
}

And then in a method we can write:

public static void ReportNegativeTemperature(int temp)
{
    Guard.Against.Positive(temp, nameof(temp));
    // Do something
}

And if we pass a positive (or zero) temp we get: System.ArgumentOutOfRangeException: Required input temp cannot be positive. (Parameter 'temp')

This is one of those simple libraries that can make basic tasks easier/more readable.

If you check this out and use it make sure you say thanks to Steve on Twitter and let him know @robertsjason sent you ;)

SHARE:

Comments (4) -

  • Lex

    2/14/2020 8:16:31 AM | Reply

    Nice lib, looks a lot like https://www.nuget.org/packages/Pitcher/ with slightly different syntax. That one's a bit more explicit about which exceptions are thrown when a condition is not met, this one abstracts that away.

    • Jason Roberts

      2/14/2020 10:02:26 AM | Reply

      Cool, thanks Lex - I'll check it out Smile

  • Erik

    3/1/2020 6:09:42 PM | Reply

    Hi,
    I remember discussing this GuardClauses library in my team. We chose  not to go this route because it doesn’t really add functionality,  and people prefered to explicitly read which exceptions would be thrown. Using tooling like GhostDoc would add potential exceptions to the generated XML docs when exceptions are  thrown directly from within the method. Another argument against the usage was that it adds a call to the stacktrace which made it a little less clear what method caused the exception. I also vaguely  remember  that stylecop was nagging about the methods that used the GuardClauses library. I think it kept generating warnings about the methods not checking the input parameters. (Because it  was being done in the library)

    But this was some time ago, so maybe things have changed Smile

    • Jason Roberts

      3/26/2020 3:07:41 AM | Reply

      Cool - thanks for the comment Erik Smile

Pingbacks and trackbacks (1)+

Add comment

Loading