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: