Refactoring Guard Clauses
Asked Answered
W

5

35

What approaches do people take (if any) in managing guard clause explosion in your classes? For example:

public void SomeMethod<T>(string var1, IEnumerable<T> items, int count)
{
    if (string.IsNullOrEmpty(var1))
    {
        throw new ArgumentNullException("var1");
    }

    if (items == null)
    {
        throw new ArgumentNullException("items");
    }

    if (count < 1)
    {
        throw new ArgumentOutOfRangeException("count");
    }

    ... etc ....
}

In the project that I am currently working on there are many classes that have a similar set of guard clauses on the public methods.

I am aware of the .NET 4.0 Code Contracts however this is not an option for our team at the moment.

Wakefield answered 20/10, 2009 at 23:27 Comment(0)
E
61

A lot of projects that I've seen use a static Guard class.

public static class Guard {
    public static void ArgumentIsNotNull(object value, string argument) {
        if (value == null)
            throw new ArgumentNullException(argument);
    }
}

It makes the code a lot cleaner, in my opinion.

Guard.ArgumentIsNotNull(arg1, "arg1");
Eckmann answered 20/10, 2009 at 23:40 Comment(5)
I was just posting the same thing. The only problem is it puts this method at the top of stack trace vs. the originating method at the top, not that it's all that huge. This pattern obviously could be used for different types to check a range of values, etc...Titmouse
Yeah, that's the only issue I've ever had with it. Although it's easy enough to find the original calling method.Eckmann
This is essentially the same thing as the classes that imitate code contracts.Lovelovebird
just used this. thanks! First line should be "public static class Guard" not "public static Guard"Prunelle
I would suggest you annotate the guard methods with the [DebuggerHiddenAttribute]. This ensures that the debugger won't stop in these methods, but return to the original method. See msdn.microsoft.com/en-us/library/… If you are using ReSharper, you can also annotate the guard methods with the [ContractAnnotationAttribute] and the argument parameter can be annotated with the [InvokerParameterName] giving you intellisense for the parameter name strings.Cosec
L
4

If you don't want to go down the Code Contracts route, one way to simplify it is to remove the braces:

public void SomeMethod<T>(string var1, IEnumerable<T> items, int count)
{
    if (string.IsNullOrEmpty(var1))
        throw new ArgumentNullException("var1");

    if (items == null)
        throw new ArgumentNullException("items");

    if (count < 1)
        throw new ArgumentOutOfRangeException("count");

    ... etc ....
}

Other than that, there are some ways that you can simulate Code Contracts, if your objection is that .Net 4.0 is not prime time yet:

http://geekswithblogs.net/Podwysocki/archive/2008/01/22/118770.aspx

Lovelovebird answered 20/10, 2009 at 23:35 Comment(6)
For god's sake, don't do this! If statements without braces is a great way to cause yourself problems down the road.Balbinder
Beware of this! Apple's infamous goto fail was an expensive result of not using braces. (full disclosure: I sometimes do not use braces, but only if the whole thing fits on one line)Albigenses
@RufusL: That happened in a programming language infamous for having no safety nets like C# has. No self-respecting programmer would ever use goto in a C# program.Lovelovebird
What safety net are you referring to?Albigenses
@RufusL: How many do you want to know about? Memory management, range protection, exception handling, IL sandboxing... Shall I go on?Lovelovebird
I thought you meant something that would apply to someone adding an extra line after an if statement like the goto fail bug, and I couldn't think of any language/compiler feature that would prevent that. Definitely agree with you on not using goto.Albigenses
J
4

You might consider refactoring to Introduce a Null Object.

Jeremy answered 21/10, 2009 at 0:3 Comment(0)
S
4

Meanwhile there's an excellent article about this here: http://haacked.com/archive/2013/01/05/mitigate-the-billion-dollar-mistake-with-aspects.aspx/

I would consider to use NullGuard.Fody as I'm excited about Fodys abilities to reduce boilerplate code

Squeamish answered 7/2, 2015 at 8:6 Comment(0)
I
4

One approach to reducing (not completely removing) number of guard clauses is to understand the cause of their existence. Quite often, it turns that we guard against values that are valid for the type of the argument, but not valid for the method that accepts them. In other words, method is defined on a subset of the domain defined by the argument type.

Solution to this category of cases is to try to define a subtype (e.g. a more restrictive interface) and to accept that type as the argument. You can find an illustrative example in this article: Why do We Need Guard Clauses?

Of course, this technique does not apply to all cases. All reference types at least allow null references. Consequently, most of our methods will be defined on part of the domain, which in turn requires a guard clause against null.

But on the positive side, this technique helps grow awareness of methods that receive arguments that are more general than desired. Plumbing that hole helps improve design in general.

Iguana answered 19/8, 2015 at 20:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.