webentwicklung-frage-antwort-db.com.de

ArgumentNullException auslösen

Angenommen, ich habe eine Methode, die ein Objekt als Argument verwendet. Nun sagen Sie, wenn diese Methode ein NULL-Argument übergeben wird, ist dies ein schwerwiegender Fehler und eine Ausnahme sollte ausgelöst werden. Lohnt es sich für mich, so etwas zu programmieren (wenn man bedenkt, dass dies ein triviales Beispiel ist):

void someMethod(SomeClass x)
{
    if (x == null){
        throw new ArgumentNullException("someMethod received a null argument!");
    }

    x.doSomething();
}

Oder ist es sicher für mich, mich darauf zu verlassen, dass es NullException auslöst, wenn es x.doSomething () aufruft?

Angenommen, someMethod ist ein Konstruktor, und x wird erst verwendet, wenn eine andere Methode aufgerufen wird. Soll ich die Ausnahme sofort auslösen oder warten, bis x benötigt wird, und dann die Ausnahme auslösen?

54
Jason Baker

Ich ziehe die ArgumentNullException der NullReferenceException vor, die eine Überprüfung des Arguments nicht bieten würde. Im Allgemeinen ist es meine Einstellung, immer auf Null zu prüfen, bevor Sie versuchen, eine Methode für ein potenziell Nullobjekt aufzurufen.

Wenn es sich bei der Methode um einen Konstruktor handelt, hängt dies von verschiedenen Faktoren ab: Gibt es auch einen öffentlichen Setter für die Eigenschaft und wie wahrscheinlich ist es, dass das Objekt tatsächlich verwendet wird? Wenn es einen öffentlichen Setter gibt, wäre es nicht sinnvoll, eine gültige Instanz über den Konstruktor bereitzustellen, und sollte nicht zu einer Ausnahme führen.

Wenn es keinen öffentlichen Setter gibt und es möglich ist, das enthaltende Objekt ohne Referenz auf das eingefügte Objekt zu verwenden, sollten Sie die Prüfung/Ausnahme verschieben, bis sie versucht wird. Ich würde denken, dass der generelle Fall wäre, dass injiziertes Objekt für das Funktionieren der Instanz wesentlich ist, und daher ist eine ArgumentNull-Ausnahme durchaus sinnvoll, da die Instanz ohne sie nicht funktionieren kann.

58
tvanfosson

Ich folge immer der Praxis von fail fast. Wenn Ihre Methode von X abhängig ist und Sie wissen, dass X in NULL übergeben werden kann, überprüfen Sie sie mit Null und lösen Sie die Ausnahme sofort aus, anstatt den Fehlerpunkt zu verlängern.

2016 update:

Beispiel aus der realen Welt. Ich empfehle dringend die Verwendung von Jetbrains Annotations .

[Pure]
public static object Call([NotNull] Type declaringType, 
                          [NotNull] string methodName, 
                          [CanBeNull] object instance)
{
    if (declaringType == null) throw new ArgumentNullException(nameof(declaringType));
    if (methodName == null) throw new ArgumentNullException(nameof(methodName));

Guard-Anweisungen wurden mit C # 6 mit dem Operator nameof erheblich verbessert.

30
Chris Marisic

Ich bevorzuge die explizite Ausnahme aus folgenden Gründen:

  • Wenn die Methode mehr als ein SomeClass-Argument enthält, können Sie angeben, um welches es sich handelt (alles andere ist im Aufrufstapel verfügbar).
  • Was ist, wenn Sie etwas tun, das einen Nebeneffekt haben kann, bevor Sie x referenzieren?
13
Joel Coehoorn

Ich stimme der Idee eines schnellen Versagens zu - es ist jedoch klug zu wissen, warum ein schnelles Versagen praktisch ist. Betrachten Sie dieses Beispiel:

void someMethod(SomeClass x)
{       
    x.Property.doSomething();
}

Wenn Sie sich auf die NullReferenceException verlassen, um Ihnen mitzuteilen, dass etwas nicht stimmte, woher wissen Sie dann, was null war? Die Stack-Ablaufverfolgung gibt Ihnen nur eine Zeilennummer, nicht die Referenz, die Null war. In diesem Beispiel könnten x oder x.Property beide null gewesen sein und ohne eine schnelle Überprüfung mit aggressiver Prüfung im Voraus auszuführen, wissen Sie nicht, um welche es sich handelt.

9
Andrew Hare

Ich würde auch die Parameterprüfung mit der expliziten ArgumentNullException vorziehen.

Betrachten der Metadaten:

 //
    // Summary:
    //     Initializes a new instance of the System.ArgumentNullException class with
    //     the name of the parameter that causes this exception.
    //
    // Parameters:
    //   paramName:
    //     The name of the parameter that caused the exception.
    public ArgumentNullException(string paramName);

Sie können sehen, dass die Zeichenfolge der Name des Parameters sein sollte (dh null), und geben Sie dem Entwickler einen Hinweis, was schief geht.

8

Es ist besser, die ArgumentNullException früher als später zu werfen. Wenn Sie es werfen, können Sie hilfreichere Informationen zu dem Problem bereitstellen als eine NullReferenceException.

5
g .

Sie sollten explizit eine ArgumentNullException auslösen, wenn Sie davon ausgehen, dass die Eingabe nicht null ist. Möglicherweise möchten Sie eine Klasse namens Guard schreiben, die dazu Hilfsmethoden bereitstellt. Ihr Code lautet also:

void someMethod(SomeClass x, SomeClass y)
{
    Guard.NotNull(x,"x","someMethod received a null x argument!");
    Guard.NotNull(y,"y","someMethod received a null y argument!");


    x.doSomething();
    y.doSomething();
}

Die NonNull-Methode führt die Nullwertprüfung durch und löst eine NullArgumentException mit der im Aufruf angegebenen Fehlermeldung aus. 

5
Szymon Rozga

1- Tun Sie dies explizit, wenn Sie keinen Nullwert wünschen. Andernfalls, wenn eine andere Person Ihren Code sieht, wird angenommen, dass das Weitergeben eines Nullwerts akzeptiert wird.

2- Machen Sie es schneller, wenn Sie können. Auf diese Weise verbreiten Sie nicht das "falsche" Verhalten einer Null, wenn dies nicht angenommen wird.

4

Wenn Sie defensiv programmieren, sollten Sie schnell ausfallen. Überprüfen Sie also Ihre Eingaben und machen Sie einen Fehler am Anfang Ihres Codes. Sie sollten nett zu Ihrem Anrufer sein und ihnen die aussagekräftigste Fehlermeldung geben, die Sie können.

3
Aaron Fischer

Ich werde dafür wahrscheinlich heruntergestimmt sein, aber ich denke ganz anders.

Wie wäre es mit einer guten Praxis namens "never pass null" und der hässlichen Exception-Prüfung zu entfernen?

Wenn der Parameter ein Objekt ist, PASSEN SIE NULL NICHT. RÜCKGABE NULL NICHT. Sie können sogar das Null-Objektmuster verwenden, um dies zu unterstützen.

Wenn dies optional ist, verwenden Sie Standardwerte (sofern Ihre Sprache dies unterstützt) oder erstellen Sie eine Überladung. 

Viel sauberer als hässliche Ausnahmen.

0
andrecarlucci

Sie können die folgende Syntax verwenden, um nicht nur eine ArgumentNullException auszulösen, sondern den Parameter als Ausnahme in den Fehlertext aufzunehmen. Z.B.;

void SomeMethod(SomeObject someObject)
{
    Throw.IfArgNull(() => someObject);
    //... do more stuff
}

Die Klasse, die zum Auslösen der Ausnahme verwendet wird, lautet:

public static class Throw
{
    public static void IfArgNull<T>(Expression<Func<T>> arg)
    {
        if (arg == null)
        {
            throw new ArgumentNullException(nameof(arg), "There is no expression with which to test the object's value.");
        }

        // get the variable name of the argument
        MemberExpression metaData = arg.Body as MemberExpression;
        if (metaData == null)
        {
            throw new ArgumentException("Unable to retrieve the name of the object being tested.", nameof(arg));
        }

        // can the data type be null at all
        string argName = metaData.Member.Name;
        Type type = typeof(T);
        if (type.IsValueType && Nullable.GetUnderlyingType(type) == null)
        {
            throw new ArgumentException("The expression does not specify a nullible type.", argName);
        }

        // get the value and check for null
        if (arg.Compile()() == null)
        {
            throw new ArgumentNullException(argName);
        }
    }
}
0
DiskJunky