Extension methods are pretty cool. They allow you to add functionality to a class or to a type’s behavior. Extension methods usually make life much easier and your code cleaner. I am going to share a few extension methods that make repetitive guard clauses, shorter and easier to read.
Guard Clauses
Guard clauses are those checks at the top of a method to validate all the parameters being passed in. Most of the time, they are used to check if an object is null, a string is empty, or that a collection at least contains something and is not empty. When the parameters do not pass the checks usually some sort of Argument Exception should be thrown. This helps to validate all the parameters before your method begins working on them and provides a better explanation than what could possibly be thrown. Without guard clauses we would have null reference exceptions all over the place which are a pain to debug.
Below I have a method that prints a heading and then a list of names. I want to validate the heading and all the names before I actually print them out. The traditional way is to have code that looks like the following:
public static void PrintNames(string heading, ICollection<string> names) { if (string.IsNullOrEmpty(heading)) throw new ArgumentNullException("heading"); if (names == null || names.Count == 0) throw new ArgumentNullException("names"); foreach (string name in names) { if (string.IsNullOrEmpty(name)) throw new ArgumentNullException("names has a null or empty item."); }
This is pretty ugly to have all over the place and this type of checking is extremely repetitive across all your methods. So I have a class of extension methods that make this cleaner and easier.
public static class GuardExtensions { public static T GuardClauseIsNull<T>(this T parameter, string name) where T : class { if (parameter == null) throw new ArgumentNullException(name); return parameter; } public static string GuardClauseIsNullOrEmpty(this string parameter, string name) { if (string.IsNullOrEmpty(parameter)) throw new ArgumentNullException(name); return parameter; } public static ICollection<T> GuardClauseCollectionEmptyOrNull<T>(this ICollection<T> list, string name) { if (list == null || list.Count == 0) throw new ArgumentNullException(name); return list; } public static ICollection<T> GuardClauseCollectionEmptyOrNullAndAnItemIsNull<T>(this ICollection<T> list, string name) where T : class { if (list == null || list.Count == 0) throw new ArgumentNullException(name); foreach (T item in list) { item.GuardClauseIsNull(name + " has a null item."); } return list; } public static ICollection<string> GuardClauseCollectionEmptyOrNullAndAnItemIsNullOrEmpty(this ICollection<string> list, string name) { if (list == null || list.Count == 0) throw new ArgumentNullException(name); foreach (string item in list) { item.GuardClauseIsNullOrEmpty(name + " has a null or empty item."); } return list; } }
The first method is a generic extension method and works on any object that derives from class, which almost all do. All these methods take in the name of the parameter, to be used in the exception message. The others are variations of this logic that also check if a collection is null or empty and optional methods to check each item. I have found these variations to be useful in different cases. This makes the calling code cleaner and less repetitive as you will see next.
Usage
I made a simple console application to show you how this works in different cases. I have different cases with different variations of null objects and lists to test with.
class Program { static void Main(string[] args) { List<string> myNames = new List<string>() { "Scott", "James", "Bob" }; List<string> myNamesWithNull = new List<string>() { "Scott", null, "Bob" }; List<string> myNamesWithEmpty = new List<string>() { "Scott", "", "Bob" }; List<string> emptyList = new List<string>(); PrintNames("The Names are:", myNames); //Run 1 PrintNames(null, myNames); //Run 2 PrintNames("The Names are:", myNamesWithNull); //Run 3 PrintNames("The Names are:", myNamesWithEmpty); //Run 4 PrintNames("The Names are:", emptyList); //Run 5 PrintNames("The Names are:", null); //Run 6 Console.ReadKey(); } public static void PrintNames(string heading, ICollection<string> names) { try { heading.GuardClauseIsNullOrEmpty("heading"); names.GuardClauseCollectionEmptyOrNull("names"); names.GuardClauseCollectionEmptyOrNullAndAnItemIsNull("names"); names.GuardClauseCollectionEmptyOrNullAndAnItemIsNullOrEmpty("names"); } catch (Exception guardException) { Console.WriteLine(guardException.GetType().ToString() + Environment.NewLine + guardException.Message); return; } Console.WriteLine(heading); foreach (string name in names) { Console.WriteLine(name); } } }
To save space after each run I comment out the previous runs. And the checking of the names collection would only use one of the extension methods instead of all three.
Output
Run 1
As you can see here the heading and names print out correctly.
Run 2
Here the heading value is null which triggers an exception from our extension method.
Run 3
In this run our extension methods catches that one of our names is null.
Run 4
Here we catch that a name is an empty string. Not all cases would we care if it was empty but the extension methods give us that flexibility.
Run 5
Here an empty list is caught.
Run 6
And finally we see that a null list of names also throws an exception.
Summary
Most of examples of extension methods are purely academic, such as counting words in a string or something that is generally just as useless. Here though these extensions for guard clauses can save us countless lines of repetitive code. Using the generic null check method covers the large majority of most guard clause usage. I am sure that you can come up with several other extension methods to cover specific types and use cases.
As always, let me know of ways to improve these guard clauses or your special use cases either in the comments or on twitter @ScottKerlagon!