Beste Möglichkeit, nach Nullparametern zu suchen (Guard Clauses)

Beste Möglichkeit, nach Nullparametern zu suchen (Guard Clauses)
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);
        }
    }
}

Verwendung:

// C# < 6
public Constructor([NotNull] object foo)
{
    Ensure.ArgumentNotNull(foo, "foo");
    ...
}

// C# >= 6
public Constructor([NotNull] object bar)
{
    Ensure.ArgumentNotNull(bar, nameof(bar));
    ...
}

Der DebuggerStepThroughAttribute ist sehr praktisch, damit ich im Falle einer Ausnahme beim Debuggen (oder wenn ich den Debugger anhänge, nachdem die Ausnahme aufgetreten ist) nicht in ArgumentNotNull lande Methode, sondern bei der aufrufenden Methode, wo die Nullreferenz actually passiert.

Ich verwende ReSharper Contract Annotations.

  • Die ContractAnnotationAttribute stellt sicher, dass ich das Argument niemals falsch schreibe ("foo" ) und benennt es auch automatisch um, wenn ich foo umbenenne Symbol.
  • Der NotNullAttribute hilft ReSharper bei der Codeanalyse. Wenn ich also new Constructor(null) mache if erhält eine Warnung von ReSharper, dass dies zu einer Ausnahme führt.
  • Wenn Sie Ihren Code nicht direkt annotieren möchten, können Sie dasselbe auch mit externen XML-Dateien tun, die Sie mit Ihrer Bibliothek bereitstellen könnten und die Benutzer optional in ihrem ReShaprer referenzieren können.

Mit einer neueren Version der C#-Sprache können Sie dies ohne zusätzliche Bibliothek oder zusätzlichen Methodenaufruf schreiben:

_ = someArg ?? throw new ArgumentNullException(nameof(someArg));
_ = otherArg ?? throw new ArgumentNullException(nameof(otherArg));

Wenn Sie zu viele Parameter in Ihren Konstruktoren haben, sollten Sie sie besser überarbeiten, aber das ist eine andere Geschichte.

Um den Boilerplate-Validierungscode zu reduzieren, schreiben viele Typen Guard-Dienstprogrammklassen wie folgt:

public static class Guard
{
    public static void ThrowIfNull(object argumentValue, string argumentName)
    {
        if (argumentValue == null)
        {
            throw new ArgumentNullException(argumentName);
        }
    }

    // other validation methods
}

(Sie können dieser Guard-Klasse andere Validierungsmethoden hinzufügen, die möglicherweise erforderlich sind).

Somit ist nur eine Codezeile erforderlich, um einen Parameter zu validieren:

    private static void Foo(object obj)
    {
        Guard.ThrowIfNull(obj, "obj");
    }