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.

Community
  • 1
  • 1
Kane
  • 16,471
  • 11
  • 61
  • 86

5 Answers5

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");
Jørn Schou-Rode
  • 37,718
  • 15
  • 88
  • 122
David Brown
  • 35,411
  • 11
  • 83
  • 132
  • 2
    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... – Wil P Oct 20 '09 at 23:42
  • Yeah, that's the only issue I've ever had with it. Although it's easy enough to find the original calling method. – David Brown Oct 20 '09 at 23:46
  • 1
    This is essentially the same thing as the classes that imitate code contracts. – Robert Harvey Oct 21 '09 at 03:25
  • just used this. thanks! First line should be "public static class Guard" not "public static Guard" – Korey Aug 25 '11 at 18:56
  • 19
    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 http://msdn.microsoft.com/en-us/library/system.diagnostics.debuggerhiddenattribute.aspx 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. – Siewers Jan 31 '13 at 08:00
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

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
  • 7
    For god's sake, don't do this! If statements without braces is a great way to cause yourself problems down the road. – EricRRichards Feb 27 '18 at 15:04
  • Beware of this! Apple's infamous [goto fail](https://embeddedgurus.com/barr-code/2014/03/apples-gotofail-ssl-security-bug-was-easily-preventable/) 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) – Rufus L Feb 12 '19 at 22:34
  • 1
    @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. – Robert Harvey Feb 12 '19 at 22:36
  • What safety net are you referring to? – Rufus L Feb 12 '19 at 22:37
  • @RufusL: How many do you want to know about? Memory management, range protection, exception handling, IL sandboxing... Shall I go on? – Robert Harvey Feb 12 '19 at 22:38
  • 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`. – Rufus L Feb 12 '19 at 22:44
4

You might consider refactoring to Introduce a Null Object.

Todd Stout
  • 3,687
  • 3
  • 24
  • 29
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

mamuesstack
  • 1,111
  • 2
  • 16
  • 34
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.

Zoran Horvat
  • 10,924
  • 3
  • 31
  • 43