24

I've noticed this code crops up a lot in my constructors:

if (someParam == null) throw new ArgumentNullException("someParam");
if (someOtherParam == null) throw new ArgumentNullException("someOtherParam");
...

I have a few constructors where several things are injected and must all be non-null. Can anyone think of a way to streamline this? The only thing I can think of is the following:

public static class ExceptionHelpers
{
   public static void CheckAndThrowArgNullEx(IEnumerable<KeyValuePair<string, object>> parameters)
   {
      foreach(var parameter in parameters)
         if(parameter.Value == null) throw new ArgumentNullException(parameter.Key);
   }
}

However, the usage of that would be something like:

ExceptionHelper.CheckAndThrowArgNullEx(new [] {
    new KeyValuePair<string, object>("someParam", someParam),
    new KeyValuePair<string, object>("someOtherParam", someOtherParam),
    ... });

... which doesn't really help streamline the code. Tuple.Create() instead of KVPs doesn't work because Tuple's GTPs aren't covariant (even though IEnumerable's GTP is). Any ideas?

KeithS
  • 70,210
  • 21
  • 112
  • 164
  • 1
    I know no way to avoid the boilerplate. I use `Contract.Requires(arg!=null);`, but it's still annoying. One of C#'s weaknesses. – CodesInChaos Aug 20 '12 at 19:31
  • duplicate of http://stackoverflow.com/questions/11522104/what-is-the-best-way-to-extend-null-check – Wouter Mar 12 '14 at 10:53
  • I'd recommend using a nice little library like [Guard](https://github.com/safakgur/guard) ;) (Disclaimer: I'm the author) – Şafak Gür Oct 12 '18 at 21:22

17 Answers17

26

Update for C# 7

You can use a throw expression with the null coalescing operator. Here is an example from that page:

public string Name
{
    get => name;
    set => name = value ?? 
        throw new ArgumentNullException(paramName: nameof(value), message: "New name must not be null");
}

Original Answer

Personally, I use the ThrowIfNull extension method. I don't know who to credit but I definitely didn't invent it. It's nice because you can do assignment with the return value:

public static T ThrowIfNull<T>(this T argument, string argumentName)
{
    if (argument == null)
    {
        throw new ArgumentNullException(argumentName);
    }
    return argument;
}

Usage:

this.something = theArgument.ThrowIfNull("theArgument");
// or in C# 6
this.something = theArgument.ThrowIfNull(nameof(theArgument));

(Although some people think it's weird to call an extension method on a null instance)

If you really want to check more than one argument at a time, your example might be more streamlined if you used a params signature like so:

public static void CheckAndThrowArgNullEx(params object[] argsAndNames)
{
    for (int i = 0; i < argsAndNames.Length; i += 2)
    {
        if (argsAndNames[i] == null)
        {
            string argName = (string)argsAndNames[i + 1];
            throw new ArgumentNullException(argName);
        }
    }
}

and the usage would be:

CheckAndThrowArgNullEx(arg1, "arg1", arg2, "arg2");
// or in C# 6
CheckAndThrowArgNullEx(arg1, nameof(arg1), arg2, nameof(arg2));

On second thought, as KeithS mentions in the comments, it would probably be better to implement this as a set of overloads rather than using params object[] like this:

static void Check(object arg1, string arg1Name) { ... }
static void Check(object arg1, string arg1Name, object arg2, string arg2Name) { ... }
// and so on...
default.kramer
  • 5,943
  • 2
  • 32
  • 50
  • Good idea and +1, but `params object[]` when you expect the params to be of definite types is a code smell. – KeithS Aug 20 '12 at 20:31
  • True - I suppose it would be cleaner to use a bunch of overloads like `Check(object arg1, string arg1Name)` for up to, say, 5 pairs of arguments+names. – default.kramer Aug 20 '12 at 20:54
15

Try this: One line.

accounts = accounts ?? throw new ArgumentNullException(nameof(accounts));

Also, use nameof(), if the variable is ever renamed you will not have to hunt down all the "variable"s, let nameof() do that.

Greg Viers
  • 3,473
  • 3
  • 18
  • 36
Russ Ebbing
  • 478
  • 5
  • 7
11

.NET 6 and beyond

There is a new method in .NET API ArgumentNullException.ThrowIfNull(someParameter).

This method is probably the best option which you can get.

C# 11 (currently as proposal)

Use new Bang Bang operator !! on a parameter to implicit check for null.

public string SomeFunction(Foo foo!!)
{
  // here, foo is already checked for null
  // ArgumentNullException(nameof(foo)) is thrown when foo = null
  return $"Here is {foo.Bar}";
}

TL;DR

The compiler will emit this code for every !! use

if (someArgument is null)
{
  throw new ArgumentNullException(nameof(someArgument));
}

Our SomeFunction will be transformed into

public string SomeFunction(Foo foo!!)
{
  if (foo is null)
  {
    throw new ArgumentNullException(nameof(foo));
  }
  return $"Here is {foo.Bar}";
}
KUTlime
  • 5,889
  • 1
  • 18
  • 29
7

There are several way to go about this.

Option A:

Break your functions into two - validation and implementation (you can see examples of this in Jon Skeet's EduLinq).

Option B:

Use code contracts that expect the parameters to be non-null.

Option C:

Using aspect oriented technologies such as code weaving to extract these checks out into an aspect. (as J Torres answered).

Option D:

Use Spec#, as CodeInChaos commented.

Option E:

???

Lennart
  • 9,657
  • 16
  • 68
  • 84
Oded
  • 489,969
  • 99
  • 883
  • 1,009
7

In c# 10 you can just do this:

ArgumentNullException.ThrowIfNull(z);

And you will got this error:

System.ArgumentNullException: Value cannot be null. (Parameter 'z')
   at System.ArgumentNullException.Throw(String paramName)
   at System.ArgumentNullException.ThrowIfNull(Object argument, String paramName)
   at ConsoleApp1.SomeClass.Join(String a, String b)

Under the hood, it use the new CallerArgumentExpression attribure.

Ygalbel
  • 5,214
  • 1
  • 24
  • 32
5

Upticks for most of you guys; your answers contributed to the solution I finally arrived at, which incorporated bits and pieces but ultimately is different from all of them.

I created a couple of static methods that work on lambda expressions of a specific form (EDIT - small change; the methods can't be generic or they will require all expressions to return the same type. Func is fine instead, with an extra condition in the GetName method to unwrap the cast):

public static class ExpressionReader
{
    /// <summary>
    /// Gets the name of the variable or member specified in the lambda.
    /// </summary>
    /// <param name="expr">The lambda expression to analyze. 
    /// The lambda MUST be of the form ()=>variableName.</param>
    /// <returns></returns>
    public static string GetName(this Expression<Func<object>> expr)
    {
        if (expr.Body.NodeType == ExpressionType.MemberAccess)
            return ((MemberExpression) expr.Body).Member.Name;

        //most value type lambdas will need this because creating the 
        //Expression from the lambda adds a conversion step.
        if (expr.Body.NodeType == ExpressionType.Convert
                && ((UnaryExpression)expr.Body).Operand.NodeType 
                     == ExpressionType.MemberAccess)
            return ((MemberExpression)((UnaryExpression)expr.Body).Operand)
                   .Member.Name;

        throw new ArgumentException(
           "Argument 'expr' must be of the form ()=>variableName.");
    }
}

public static class ExHelper
{
    /// <summary>
    /// Throws an ArgumentNullException if the value of any passed expression is null.
    /// </summary>
    /// <param name="expr">The lambda expressions to analyze. 
    /// The lambdas MUST be of the form ()=>variableName.</param>
    /// <returns></returns>
    public static void CheckForNullArg(params Expression<Func<object>>[] exprs)
    {
        foreach (var expr in exprs)
            if(expr.Compile()() == null)
                throw new ArgumentNullException(expr.GetName());
    }
}

... which can be used thusly:

//usage:

ExHelper.CheckForNullArg(()=>someParam, ()=>someOtherParam);

This reduces the boilerplate to one line, without third-party tools. The ExpressionReader, and thus the exception-generating method, work on any lambda of the form ()=>variableName that compiles in the caller, meaning it works for local variables, parameters, instance fields and instance properties, at least. I haven't checked to see if it works on statics.

KeatsPeeks
  • 19,126
  • 5
  • 52
  • 83
KeithS
  • 70,210
  • 21
  • 112
  • 164
3
public class TestClass
{
    public TestClass()
    {
       this.ThrowIfNull(t=>t.Str, t=>t.Test);
       //OR
       //this.ThrowIfNull(t => t.X)
       //    .ThrowIfNull(t => t.Test);
    }
    string Str = "";
    public TestClass Test {set;get;}
}


public static class SOExtension
{
    public static T ThrowIfNull<T>(this T target, params Expression<Func<T, object>>[] exprs)
    {
        foreach (var e in exprs)
        {
            var exp = e.Body as MemberExpression;
            if (exp == null)
            {
                throw new ArgumentException("Argument 'expr' must be of the form x=>x.variableName");
            }

            var name = exp.Member.Name;
            if (e.Compile()(target) == null)
                throw new ArgumentNullException(name,"Parameter [" + name + "] can not be null");

        }
        return target;
    }
}
L.B
  • 114,136
  • 19
  • 178
  • 224
3

In c# 7 can be done like this:

_ = someParam ?? throw new ArgumentNullException(nameof(someParam));

After release optimisation you will get:

if (someParam == null)
    throw new ArgumentNullException(nameof(someParam));
kunitdmi
  • 31
  • 1
2

If you aren't opposed to third party utilities, PostSharp provides clean ways to inject such validations. This blog post provides a solution to your problem.

Update: See new Validating-parameters features in PostSharp 3

Michael Freidgeim
  • 26,542
  • 16
  • 152
  • 170
Jaime Torres
  • 10,365
  • 1
  • 48
  • 56
1

How about an extension method?

public static void ThrowExceptionIfNull(this object argument, string argumentName)
{
    if(argument == null)
        throw new ArgumentNullException(argumentName);
} 

Then your code at least reads a little more fluently:

someParam.ThrowExceptionIfNull("someParam");

Otherwise, I would agree with the others to split the functionality or use AOP (ie. PostSharp)

Justin Pihony
  • 66,056
  • 18
  • 147
  • 180
  • 1
    This would work. I generally dislike the use of extensions on Object (because they show up in EVERY IntelliSense list on EVERY variable or property) but the alternatives seem to be more trouble than they're worth. I might include some simple expression parsing similar to PostSharp's ExpressionReader; get the name of the single leaf Expression of the lambda and use it as the parameter name for the exception. That requires the method to be flipped back around to true static context. – KeithS Aug 20 '12 at 19:48
1

Well, the boilerplate is hard to avoid. You could switch to using the Bertrand Meyers' Eiffel programming language and EiffelStudio instead of C# and Visual Studio and start practicing "design by contract".

Eiffel is fully CLR-compliant these days.

Nicholas Carey
  • 71,308
  • 16
  • 93
  • 135
1

There are a lot of valid solutions already, but here's my take:

using System.Diagnostics;
using System.Reflection;

public SomeConstructor(int? par1, int? par2, string par3)
{
    CheckThrowNull(par1, par2, par3);
    //rest of constructor code...
}

///<param name="values"> Values must be given in order </param>
public static void CheckThrowNull(params object[] values)
{
    StackTrace stackTrace = new StackTrace();
    ParameterInfo[] parameters = stackTrace.GetFrame(1).GetMethod().GetParameters(); //get calling method's parameters (or constructor)
    if (parameters.Length != values.Length)
    {
        throw new ArgumentException("Incorrect number of values passed in");
    }
    for (int i = 0; i < parameters.Length; i++)
    {
        if (values[i] == null)
        {   
            //value was null, throw exception with corresponding parameter name
            throw new ArgumentNullException(parameters[i].Name);
        }
    }
}

The general idea is that two parallel arrays are established, one of type ParameterInfo, and one containing the values of the parameter. The latter has to passed in because parameter values aren't easily (and I think impossible) obtainable via reflection. To give credit where it is due, I found how to get the calling method here: http://www.csharp-examples.net/reflection-calling-method-name/

Personally, I don't like using System.Diagnosics except for debugging, so I would make a slight modification, having calling code be:

CheckThrowNull(MethodBase.GetCurrentMethod(), par1, par2, par3);

and the method being

CheckThrowNull(MethodBase method, params object[] values)
{
    ParameterInfo[] parameters = method.GetParameters();
    //rest of code same
}

The down-side is its a little non-extensible and can't easily be made to check if just some of the arguments are null.

DPenner1
  • 10,037
  • 5
  • 31
  • 46
1

I wrote benchmark application with multiple variations of extracting argument name (via anonymous class + reflection / MemberExpression / Func / etc)

Github link to benchmark sources: https://github.com/iXab3r/NullCheckCompetition

I got results, that are showing, that the fastest method is through use of anonymous class.

.NET 40 / X64

Fail (i.e. argument IS null and name extraction method is executed)

  • FailAnonymousClass 67.87 ns
  • FailDoubleLambda 643.98 ns
  • FailLazyAnonymousClass 69.36 ns
  • FailRawCheck 1.08 ns
  • FailSingleLambda 643.27 ns

Success (i.e. argument is not null)

  • SuccessAnonymousClass 6.33 ns
  • SuccessDoubleLambda 8.48 ns
  • SuccessLazyAnonymousClass 8.78 ns
  • SuccessRawCheck 1.08 ns
  • SuccessSingleLambda 628.28 ns
Xab3r
  • 29
  • 1
0

I think most of the above are ok but none of them are really an improvement to what you already have so I would just go for the KIS, Keep It Simple, and that is what you started with.

It's clean, extremly readable and its fast. The only thing it's a bit long

Tomas Hesse
  • 385
  • 3
  • 10
0

Update for C# 10 (.NET >= 6):

_person = person.ThrowIfNull();

public static T ThrowIfNull<T>(this T? argument, string? message = default, [CallerArgumentExpression("argument")] string? paramName = default)
{
    return argument ?? throw new ArgumentNullException(paramName, message);
}

Reference: https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/caller-argument-expression

Luis Cantero
  • 1,278
  • 13
  • 11
0

With C# 11 and .NET 6.0 you can do this:

public bool DoSomething(string name)
{
    ArgumentNullException.ThrowIfNull(name);

    // Do your stuff, name is not null
}

ArgumentNullException.ThrowIfNull Method

Gian Marco
  • 22,140
  • 8
  • 55
  • 44
-1

It is actually possible to retrieve the argument name from the lambda expression without going through the Expression type. This is how it can be done:

static void SampleMethod(string arg1)
{
    ThrowIfNull(() => arg1);
    // continue to other normal stuff here...
}

public static void ThrowIfNull<T>(Func<T> lambda) 
    where T : class
{
    if (lambda() == null)
    {
        throw new ArgumentNullException(lambda.Target.GetType().GetFields()[0].Name);
    }
}
nawfal
  • 70,104
  • 56
  • 326
  • 368
Tony Chu
  • 1
  • 3
  • Anyone using this, a word of caution: This is horribly wrong if you have multiple validations to make. E.g. `ThrowIfNull(() => arg1); ThrowIfNull(() => arg2);`. Here in both cases the name is `arg1`. `GetFields()[0]` is the culprit here. Each `Target`, has entire fields of the method (in this case arg1 and arg2), and not just the lambda in question. – nawfal Jun 21 '20 at 14:08