Ja, es gibt gute Gründe:
- Es identifiziert genau, was null ist, was aus a möglicherweise nicht ersichtlich ist
NullReferenceException
- Der Code schlägt bei ungültiger Eingabe fehl, auch wenn eine andere Bedingung bedeutet, dass der Wert nicht dereferenziert wird
- Die Ausnahme tritt auf, bevor die Methode andere Nebenwirkungen haben kann, die Sie möglicherweise vor der ersten Dereferenzierung erreichen
- Sie können also sicher sein, dass Sie nicht gegen den Vertrag verstoßen, wenn Sie den Parameter an etwas anderes übergeben
- Es dokumentiert die Anforderungen Ihrer Methode (die Verwendung von Code-Verträgen ist dafür natürlich noch besser)
Nun zu Ihren Einwänden:
- Es ist langsamer : Haben Sie festgestellt, dass dies tatsächlich der Engpass in Ihrem Code ist, oder raten Sie? Nullitätsprüfungen sind sehr schnell und in den allermeisten Fällen nicht der Engpass
- Es macht es schwieriger, den Code zu pflegen : Ich denke das Gegenteil. Ich denke, es ist einfacher , Code zu verwenden, bei dem klargestellt wird, ob ein Parameter null sein kann oder nicht, und bei dem Sie sicher sind, dass diese Bedingung durchgesetzt wird.
Und für Ihre Behauptung:
Offensichtlich löst der Code, der s verwendet, trotzdem eine Ausnahme aus.
"Ja wirklich?" Erwägen:
void f(SomeType s)
{
// Use s
Console.WriteLine("I've got a message of {0}", s);
}
Das nutzt s
, aber es löst keine Ausnahme aus. Wenn es ungültig ist s
, null zu sein, und dies darauf hinweist, dass etwas nicht stimmt, ist eine Ausnahme hier das am besten geeignete Verhalten.
Nun ist es eine andere Sache, wo Sie diese Überprüfungen der Argumentvalidierung platzieren. Sie können sich dafür entscheiden, dem gesamten Code in Ihrer eigenen Klasse zu vertrauen, ohne sich um private Methoden zu kümmern. Sie können sich dafür entscheiden, dem Rest Ihrer Baugruppe zu vertrauen, ohne sich um interne Methoden zu kümmern. Sie sollten mit ziemlicher Sicherheit die Argumente für öffentliche Methoden validieren.
Eine Randnotiz: Die Einzelparameter-Konstruktorüberladung von ArgumentNullException
sollte nur der Parametername sein, daher sollte Ihr Test sein:
if (s == null)
{
throw new ArgumentNullException("s");
}
Alternativ können Sie eine Erweiterungsmethode erstellen, die Folgendes zulässt:
s.ThrowIfNull("s");
In meiner Version der (generischen) Erweiterungsmethode wird der ursprüngliche Wert zurückgegeben, wenn er nicht null ist. So können Sie Folgendes schreiben:
this.name = name.ThrowIfNull("name");
Sie können auch eine Überladung haben, die den Parameternamen nicht annimmt, wenn Sie sich nicht zu sehr darum kümmern.