Ich sehe das folgende Codemuster überall in der Codebasis meines Unternehmens (.NET 3.5-Anwendung):
bool Foo(int barID, out Baz bazObject) {
try {
// do stuff
bazObject = someResponseObject;
return true;
}
catch (Exception ex) {
// log error
return false;
}
}
// calling code
BazObject baz = new BazObject();
fooObject.Foo(barID, out baz);
if (baz != null) {
// do stuff with baz
}
Ich versuche, mich darum zu Foo
kümmern, warum Sie dies tun würden, anstatt die Methode einfach die ID nehmen und ein Baz
Objekt zurückgeben zu lassen, anstatt einen Wert zurückzugeben, der nicht verwendet wird, und das tatsächliche Objekt als Referenz- oder Ausgabeparameter zu haben.
Gibt es einen versteckten Vorteil dieses Codierungsstils, den ich vermisse?
c#
code-quality
coding-style
Wayne Molina
quelle
quelle
baz
seinnull
und das zurückgegebenebool
Wesenfalse
ist nicht gleichwertig.new BazObject()
ist nienull
, es sei denn ,bazObject
aktualisiert wird , bevor dieException
in geworfen wirdFoo
, wennfalse
zurückgegeben wird ,baz
wird es nie seinnull
. Es würde enorm helfen, wenn die Spezifikation fürFoo
verfügbar wäre. In der Tat ist dies vielleicht das schwerwiegendste Problem, das dieser Code aufweist.Antworten:
Normalerweise verwenden Sie dieses Muster, damit Sie Code wie folgt schreiben können:
Es wird beispielsweise in der CLR für TryGetValue in der Dictionary-Klasse verwendet. Es vermeidet Redundanz, aber Out- und Ref-Parameter schienen mir immer etwas chaotisch
quelle
Dies ist alter C-Code, bevor es Ausnahmen gab. Der Rückgabewert gab an, ob die Methode erfolgreich war oder nicht, und wenn dies der Fall war, wurde der Parameter mit dem Ergebnis gefüllt.
In .net haben wir Ausnahmen für diesen Zweck. Es sollte keinen Grund geben, diesem Muster zu folgen.
[Bearbeiten] Es gibt offensichtlich Auswirkungen auf die Leistung bei der Ausnahmebehandlung. Vielleicht hat das etwas damit zu tun. In diesem Code-Snippet wird jedoch bereits eine Ausnahme ausgelöst. Es wäre sauberer, es einfach den Stapel nach oben bewegen zu lassen, bis es an einer geeigneteren Stelle gefangen ist.
quelle
if (baz.Select())
aber meistens wird der Rückgabewert einfach weggeworfen und der Wert gegen null oder eine Eigenschaft geprüft.Angesichts des Code-Snippets sieht es völlig sinnlos aus. Für mich würde das anfängliche Codemuster darauf hinweisen, dass null für BazObject ein akzeptabler Fall wäre und die Bool-Rückgabe ein Maß für die sichere Bestimmung eines Fehlerfalls ist. Wenn der folgende Code war:
Das wäre für mich sinnvoller, es so zu machen. Vielleicht ist dies eine Methode, die jemand vor Ihnen verwendet hat, um sicherzustellen, dass baz als Referenz übergeben wurde, ohne zu verstehen, wie Objektparameter in C # tatsächlich funktionieren.
quelle
Manchmal ist dieses Muster nützlich, wenn Sie als Anrufer sich nicht darum kümmern sollen, ob der zurückgegebene Typ ein Referenz- oder ein Werttyp ist. Wenn Sie eine solche Methode aufrufen, um einen Werttyp abzurufen, benötigt dieser Werttyp entweder einen festgelegten ungültigen Wert (z. B. double.NaN) oder Sie benötigen eine andere Methode zur Bestimmung des Erfolgs.
quelle
Die Idee ist, einen Wert zurückzugeben, der angibt, ob der Prozess erfolgreich war, und Code wie diesen zulässt:
Wenn das Objekt nicht null sein kann (was in Ihrem Beispiel korrekt erscheint), gehen Sie besser wie folgt vor:
Wenn das Objekt kann null sein, sind Ausnahmen der Weg zu gehen:
Es ist ein allgemeines Muster, das in C verwendet wird, wo es keine Ausnahmen gibt. Dadurch kann die Funktion eine Fehlerbedingung zurückgeben. Ausnahmen sind im Allgemeinen eine viel sauberere Lösung.
quelle