For example, you usually don\'t want parameters in a constructor to be null, so it\'s very normal to see some thing like
if (someArg == null)
{
throw new Arg
public static class Ensure
{
/// <summary>
/// Ensures that the specified argument is not null.
/// </summary>
/// <param name="argumentName">Name of the argument.</param>
/// <param name="argument">The argument.</param>
[DebuggerStepThrough]
[ContractAnnotation("halt <= argument:null")]
public static void ArgumentNotNull(object argument, [InvokerParameterName] string argumentName)
{
if (argument == null)
{
throw new ArgumentNullException(argumentName);
}
}
}
usage:
// C# < 6
public Constructor([NotNull] object foo)
{
Ensure.ArgumentNotNull(foo, "foo");
...
}
// C# >= 6
public Constructor([NotNull] object bar)
{
Ensure.ArgumentNotNull(bar, nameof(bar));
...
}
The DebuggerStepThroughAttribute
comes in quite handy so that in case of an excpetion while debugging (or when I attach the debugger after the exception occurred) I will not end up inside the ArgumentNotNull
method but instead at the calling method where the null reference actually
happend.
I am using ReSharper Contract Annotations.
ContractAnnotationAttribute
makes sure that I never misspell
the argument ("foo"
) and also renames it automatically if I rename
the foo
symbol. NotNullAttribute
helps ReSharper with code analysis. So if I do new Constructor(null)
if will get a warning from ReSharper that this will lead to an exception. You might try my Heleonix.Guard library, which provides guard functionality.
You can write guard clauses like below:
// C# 7.2+: Non-Trailing named arguments
Throw.ArgumentNullException(when: param.IsNull(), nameof(param));
// OR
// Prior to C# 7.2: You can use a helper method 'When'
Throw.ArgumentNullException(When(param.IsNull()), nameof(param));
// OR
Throw.ArgumentNullException(param == null, nameof(param));
// OR
Throw.ArgumentNullException(When (param == null), nameof(param));
It provides throwing of many existing exceptions, and you can write custom extension methods for custom exceptions. Also, the library refers to the 'Heleonix.Extensions' library with predicative extensions like IsNull
, IsNullOrEmptyOrWhitespace
, IsLessThan
and many more to check your arguments or variables against desired values. Unlike some other guard libraries with fluent interfaces, these extensions do not generate intermediate objects, and since implementation is really straightforward, they are performant.
If you have too many parameters in your constructors, you'd better revise them, but that's another story.
To decrease boilerplate validation code many guys write Guard utility classes like this:
public static class Guard
{
public static void ThrowIfNull(object argumentValue, string argumentName)
{
if (argumentValue == null)
{
throw new ArgumentNullException(argumentName);
}
}
// other validation methods
}
(You can add other validation methods that might be necessary to that Guard class).
Thus it only takes one line of code to validate a parameter:
private static void Foo(object obj)
{
Guard.ThrowIfNull(obj, "obj");
}
The simplest approach I've found is inspired by Dapper's use of anonymous types. I've written a Guard class that uses anonymous types to get name of properties. The guard itself is the following
public class Guard
{
public static void ThrowIfNull(object param)
{
var props = param.GetType().GetProperties();
foreach (var prop in props)
{
var name = prop.Name;
var val = prop.GetValue(param, null);
_ = val ?? throw new ArgumentNullException(name);
}
}
}
The use is then
...
public void Method(string someValue, string otherValue)
{
Guard.ThrowIfNull(new { someValue, otherValue });
}
...
When the ArgumentNullException is thrown and the correctly named property will be displayed.