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.
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.
I found these 3 libraries which had more downloads on nuget.com
Library Name | Last Updated | Supported Frameworks |
---|---|---|
Ardalis.GuardClauses | 4 months ago | .NET 6, .NET Standard 2.0, .NET Framework 4.5.1 |
Dawn.Guard | 3/31/2020 | .NET Standard 1.0 |
Guard.Net | 9 months ago | .NET 5.0 |
For this article, I’ll make use of Ardalis.GuardClauses
library as it is supporting latest frameworks.
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.
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?
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.
Karthik is a passionate Full Stack developer working primarily on .NET Core, microservices, distributed systems, VUE and JavaScript. He also loves NBA basketball so you might find some NBA examples in his posts and he owns this blog.
In this post, we’ll see how to test gRPC Server applications using different clients. And… Read More
In this post, we'll create a new gRPC project in ASP.NET Core and see what's… Read More
In this blog post, we’ll see how to run dotnet core projects without opening visual… Read More
Programmatically evaluating policies is useful when we want to provide access or hide some data… Read More
We saw how we could set up policy-based authorization in our previous article. In this… Read More
What is policy-based authorization and how to set up policy-based authorization with handlers and policies… Read More
This website uses cookies.