How to create .NET Custom Guard Clause

September 30 2024

 
Many thanks to the sponsors who make it possible for this newsletter to be free for readers.

 

• Join Postman CTO, Ankit Sobti, and Head of Customer Experience and Success, Kristine Chin, at this webinar which delivers the information you need to maximize the success of your API products, reduce friction to collaboration, and to provide a world-class experience for your developers, partners, and customers.
Join here.

 
 

The Background

 
 

Guard clauses in .NET are a programming practice used for improving the readability and reliability of code. They are simple checks at the beginning of a function or a method that validate inputs or conditions before proceeding with the rest of the code.

 

Guard clauses in .NET effectively address several common programming problems: they reduce complexity and increase readability by preventing deeply nested code structures; enhance code safety and reliability by validating inputs or conditions at the outset, thus averting potential runtime errors or unexpected behavior; and they clarify the code's intent by explicitly stating the preconditions needed for subsequent code to execute correctly.

 

This not only makes the code easier to understand but also simplifies maintenance and future modifications, as the requirements and constraints are clearly laid out at the beginning of the method or function.

 

How to implement it?

 

Let's take a look deeply!

 
 

Without Custom Guard Clause 

 
 

Under normal circumstances, this would be a common piece of code you would see in an application.

public class Person
{
    public string Name { get; private set; }

    public Person(string name)
    {
        if (string.IsNullOrEmpty(name))
        {
            throw new ArgumentException("Name cannot be null or whitespace.", nameof(name));
        }

        Name = name;
    }
}
There is nothing unknown here. We check if the name is filled in and throw an exception if it is not.

 

Note: I am not a supporter of this practice that exceptions are thrown in situations when it is not necessary. In this case, I would use the Result object with the Failure status. Certainly, this issue is about another problem that we are solving, so we will stick to exceptions.

 

What's wrong here?

 

Nothing specific. But code readability is not something.

 

Just imagine, let's now insert another check for us (is it in the right format, good length, etc...). The function will have 20 lines of code just for checking.

 

Let's make it sexier... :)

 
 

Custom Guard Clause

 
 

We will create a static class Ensure. I like to call it that, so that one can immediately conclude what it is about.

 

Within it, we will add the first method that the class will check.

 

This code will actually read in English:.

public static class Ensure
{
    public static void NotNullOrEmpty(string? value,
        string? paramName = null)
    {
        if(string.IsNullOrEmpty(value))
        {
            throw new ArgumentException("The value can't be null", 
            paramName);
        }
    }
}
If this is the case, the job and responsibility of throwing the exception is taken over by the Guard Clause class.

 

In this way, we have a clean and legibly written method.

 

We can see that below:

public Person(string name)
{
    Ensure.NotNullOrEmpty(name);

    // Logic
}

 

Use a help of CallerArgumentExpression 

 
 

Instead of constantly passing the name of the parameter for which an exception is thrown, which was passed as paranName in the NotNullOrEmpty() function, you can use the attribute CallerArgumentExpression("value") , where value represents the attribute for which we need a name.

 

What will happen?

 

At runtime, this value will be read and assigned to the paramName attribute.

 

This can be very useful in many situations, and we avoid hardcoding the parameter names and the potential error of writing the wrong parameter.

 

Take a look here:

public static class Ensure
{
    public static void NotNullOrEmpty(string? value, 
        [CallerArgumentExpression("value")] string? paramName = null)
    {
        if(string.IsNullOrEmpty(value))
        {
            throw new ArgumentException("The value can't be null", 
            paramName);
        }
    }
}

 

Check these libraries

 
 

Today I did not invent electricity like Nikola Tesla.

 

Many developers have already created quality libraries for the same purpose.

 

 

Ardalis
Dawn
Throw

 

Whichever you choose, you won't have any problems. And if you want more control, you can always create your own custom, as I showed.

 
 

Wrapping up

 
 

In today's issue, I showed you how to improve readability and shift the responsibility of throwing exceptions (if necessary) to another class that should handle it.

 

And in this way, you will increase the readability of your method that deals with logic. By using Guard Clauses.

 

I showed you how to create your own Custom Guard Clause.

 

I explained what the CallerArgumentExpression attribute is and how to use it.

 

And finally, if you wouldn't do it, I gave you an example of 3 existing libraries that do it in an excellent way.

 

That's all from me today.

There are 3 ways I can help you:

My Design Patterns Ebooks

1. Design Patterns that Deliver

This isn’t just another design patterns book. Dive into real-world examples and practical solutions to real problems in real applications.Check out it here.


1. Design Patterns Simplified

Go-to resource for understanding the core concepts of design patterns without the overwhelming complexity. In this concise and affordable ebook, I've distilled the essence of design patterns into an easy-to-digest format. It is a Beginner level. Check out it here.


Join TheCodeMan.net Newsletter

Every Monday morning, I share 1 actionable tip on C#, .NET & Arcitecture topic, that you can use right away.


Sponsorship

Promote yourself to 14,250+ subscribers by sponsoring this newsletter.



Join 14,250+ subscribers to improve your .NET Knowledge.

Subscribe to
TheCodeMan.net

Subscribe to the TheCodeMan.net and be among the 14,250+ subscribers gaining practical tips and resources to enhance your .NET expertise.