What are Guard Clauses in .NET

What are Guard Clauses?

A guard in general is to protect against the damage that may happen in the future.

In computer programming, a guard is a boolean expression that must evaluate to true if the program execution is to continue in the branch in question

wikipedia

Failing fast is a good strategy when writing code. It allows us to short-circuit the code execution. Guard clauses are a technique to achieve fast failing.

How to guard a method?

Let’s say we have the following method

bool SendEmail(string emailAddress)
{
    return _repo.SendEmail(emailAddress);
}

Given an email address, the SendEmail method sends an email to the user.

But, what if we pass a NULL or EMPTY value to our method. We can raise an exception if the input is not valid or null or blank etc (not validating the email address at it may distract the intent)

Here is our revised code

bool SendEmail(string emailAddress) 
{
	if (string.IsNullOrWhiteSpace(emailAddress)) {
		throw new ArgumentNullException(nameof(emailAddress));
	}
	
	return _repo.SendEmail(emailAddress);
}

Throwing an ArgumentNullException when the email address is null or whitespace is a guard here.

Great. This is all looking good.

What if we want to check the inputs for null or check if the list has values across the project and raise appropriate exceptions?

Well, we can write these checks all over the project but this leads to code duplication all over the place. Let’s see what libraries we have for guard clauses.

Available Guard Clauses Libraries

I found these 3 libraries which had more downloads on nuget.com

Library NameLast UpdatedSupported Frameworks
Ardalis.GuardClauses4 months ago .NET 6, .NET Standard 2.0, .NET Framework 4.5.1
Dawn.Guard 3/31/2020 .NET Standard 1.0
Guard.Net9 months ago .NET 5.0

For this article, I’ll make use of Ardalis.GuardClauses library as it is supporting latest frameworks.

Refactoring our method using Ardalis.GuardClauses

Let’s try to refactor our SendEmail method with Guard.Against.NullOrWhiteSpace method.

bool SendEmail(string emailAddress) 
{
	Guard.Against.NullOrWhiteSpace(emailAddress, nameof(emailAddress));
	return _repo.SendEmail(emailAddress);
}

That’s it! We went from this

if (string.IsNullOrWhitespace(emailAddress)) {
    throw new ArgumentNullException(nameof(emailAddress));
}

to this

Guard.Against.NullOrWhiteSpace(emailAddress, nameof(emailAddress));

Looks good right.

Most used guard in my opinion: Guard.Against.Null

When supplying dependencies through class constructors we usually perform ?? (null-coalescing-operator) against the parameters to avoid throwing null reference exceptions. We do something like this.

public class UserManager
    {
        private readonly IUserRepository _userRepo;
        private readonly IDepartmentRepsitory _deptRepo;
        private readonly IEmailService _emailService;
        private readonly ILogger _logger;

        public UserManager(IUserRepository userRepo, IDepartmentRepsitory deptRepo, IEmailService emailService, ILogger logger)
        {
            _userRepo = userRepo ?? throw new ArgumentNullException(nameof(userRepo));
            _deptRepo = deptRepo ?? throw new ArgumentNullException(nameof(deptRepo));
            _emailService = emailService ?? throw new ArgumentNullException(nameof(emailService));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }
    }

With Guard.Against.Null we can transform the above code into this.

public class UserManager
    {
        private readonly IUserRepository _userRepo;
        private readonly IDepartmentRepsitory _deptRepo;
        private readonly IEmailService _emailService;
        private readonly ILogger _logger;

        public UserManager(IUserRepository userRepo, IDepartmentRepsitory deptRepo, IEmailService emailService, ILogger logger)
        {
            _userRepo = Guard.Against.Null(userRepo, nameof(userRepo));
            _deptRepo = Guard.Against.Null(deptRepo, nameof(deptRepo));
            _emailService = Guard.Against.Null(emailService, nameof(emailService));
            _logger = Guard.Against.Null(logger, nameof(logger));
        }
    }

The code is now more concise when compared with null coalescing checks right?

Supported Guard clauses in Ardalis.GuardClauses

  • Guard.Against.Null (throws if input is null)
  • Guard.Against.NullOrEmpty (throws if string, guid 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.EnumOutOfRange (throws if a enum value is outside a provided Enum 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)

Do we really need a library for Guard classes?

It depends. The library we used in this article packs a bunch of useful guard methods which we can use on a daily basis. Ex: NullOrWhiteSpace, Zero

But, if we need only a couple of methods from Ardalis.GuardClauses then I think it may not be useful to add it as a dependency to our project.

Let’s say we use only null reference guards in our project, then it’s better we can create a static method and utilize them everywhere.

We can write a static method that does the same thing as Guard.Against.Null

public static class GuardX
{
    public static T ThrowIfNull<T>(T input, string message)
    {
        if (input is null) throw new ArgumentNullException(message);

        return input;
    }
}

And while guarding, we can do this

_userRepo = GuardX.ThrowIfNull(userRepo, nameof(userRepo));

If we have to check if a collection is empty, we can write another static method and use it. Again, its upto you.

References

  1. Ardalis.GuardClauses
  2. Guard – Wikipedia