A guard clause represents a condition the code must meet before executing a method. Essentially, it’s a type of code that “guards” against continuing the execution of the method if certain conditions aren’t met.In most cases, guard clauses are implemented at the beginning of a method to throw an exception early when the conditions necessary for the method’s execution are not satisfied. Throwing an exception allows callers to catch the error without the need to implement a more complex communication mechanism.We already stated that we use constructor injection to inject the required dependencies reliably. However, nothing fully guarantees us that the dependencies are not null. Ensuring a dependency is not null is one of the most common guard clauses, which is trivial to implement. For example, we could check for nulls in the controller by replacing the following:
_locationService = locationService;
With the following:
_locationService = locationService ??
throw new ArgumentNullException(nameof(locationService));
The preceding code uses a throw expression from C# 7 (See Appendix A for more information). The ArgumentNullException type makes it evident that the locationService parameter is null. So if the locationService parameter is null, an ArgumentNullException is thrown; otherwise, the locationService parameter is assigned to the _locationService member.Of course, with the introduction of the nullable reference types (see Appendix A), receiving a null argument is less likely yet still possible.
A built-in container will automatically throw an exception if it can’t fulfill all dependencies during the instantiation of a class (such as a controller). That does not mean that all third-party containers act the same.
Moreover, that does not protect you from passing null to a class you manually instantiates, nor that a method will not receive a null value. I recommend adding guards even since they are less mandatory now. The tooling can handle most of the work for us, leading to only a minor time overhead.
Furthermore, suppose you are writing code consumed by other projects, like a library. In that case, adding guards is more important since nothing guarantees that the consumers of that code have nullable reference type checks enabled.
When we need to validate a parameter and don’t need an assignment, like with most parameters of a constructor, we can use the following helper, and the BCL handles the check for us:
ArgumentNullException.ThrowIfNull(locationService);
When we need to validate a string and want to ensure it is not empty, we can use the following instead:ArgumentException.ThrowIfNullOrEmpty(name);Of course, we can always revert to if statements to validate parameters. When doing so, we must ensure we throw relevant exceptions. If no pertinent exceptions exist, we can create one. Creating custom exceptions is a great way to write manageable applications.Next, we revisit an (anti-)pattern while exploring the singleton lifetime replacing it.