Sowohl in SQL als auch in C # habe ich Output-Parameter nie wirklich gemocht. Ich habe auch nie Parameter ByRef in VB6 übergeben. Etwas über das Zählen von Nebenwirkungen, um etwas zu erledigen, stört mich nur.
Ich weiß, dass es ein Weg ist, nicht mehrere Ergebnisse von einer Funktion zurückzugeben, aber ein Rowset in SQL oder ein komplexer Datentyp in C # und VB funktionieren genauso gut und scheinen mir selbstdokumentierender zu sein.
Ist etwas falsch mit meinem Denken, oder gibt es Ressourcen aus autoritativen Quellen, die mich unterstützen? Was ist deine persönliche Meinung dazu und warum? Was kann ich Kollegen sagen, die mit Ausgabeparametern arbeiten möchten, die sie dazu bringen könnten, verschiedene Strukturen zu verwenden?
EDIT: Interessanter Turn - der Ausgabeparameter, nach dem ich diese Frage gestellt habe, wurde anstelle eines Rückgabewerts verwendet. Wenn der Rückgabewert "ERROR" ist, sollte der Aufrufer dies als Ausnahme behandeln. Ich habe das gemacht, aber nicht mit der Idee zufrieden. Ein Mitarbeiter wurde nicht über die Notwendigkeit informiert, mit dieser Bedingung umzugehen, und als Folge davon ging viel Geld verloren, da das Verfahren stillschweigend fehlschlug!
Bob Martin schrieb über diesen Clean Code. Ausgangsparameter brechen die Grundidee einer Funktion.
output = someMethod(input)
Ausgabeparameter können ein Code-Geruch sein, der anzeigt, dass Ihre Methode zu viel tut. Wenn Sie mehr als einen Wert zurückgeben müssen, macht die Methode wahrscheinlich mehr als eine Sache. Wenn die Daten eng verwandt sind, würde es wahrscheinlich von einer Klasse profitieren, die beide Werte enthält.
Natürlich ist das nicht IMMER der Fall, aber ich habe festgestellt, dass dies normalerweise der Fall ist.
Mit anderen Worten, ich denke, Sie haben Recht, sie zu vermeiden.
Sie haben ihren Platz. Int32.TryParse-Methode ist ein gutes Beispiel für eine effektive Verwendung eines out-Parameters.
%Vor%Ich sehe auch sehr wenig Verwendung von out / ref-Parametern, obwohl es in SQL manchmal einfacher ist, einen Wert durch einen Parameter als durch ein Resultset zu übergeben (was dann die Verwendung eines DataReader usw. erfordern würde).
Aber wie es der Zufall wollte, habe ich gerade eine so seltene Funktion in C # erstellt. Es validierte eine tabellenartige Datenstruktur und gab die Anzahl der Zeilen und Spalten zurück (was schwierig zu berechnen war, da die Tabelle Zeilenspalten / Spalten wie in HTML haben könnte). In diesem Fall wurde die Berechnung beider Werte gleichzeitig durchgeführt. Wenn man es in zwei Funktionen aufteilen würde, hätte das doppelte Code-, Speicher- und CPU-Zeitanforderungen zur Folge. Einen benutzerdefinierten Typ nur für diese eine Funktion zu erstellen, scheint mir ein Overkill zu sein.
Also - es gibt Zeiten, in denen sie das Beste sind, aber meistens kann man ohne sie gut auskommen.
Die OUTPUT
-Klausel in SQL Server 2005 ist ein großer Schritt nach vorn alle Feldwerte für Zeilen, die von Ihren DML-Anweisungen betroffen sind. Ich denke, dass es viele Situationen gibt, in denen dies die Ausgabeparameter überflüssig macht.
In VB6 sind ByRef-Parameter gut zum Übergeben von ADO-Objekten.
Abgesehen von diesen zwei spezifischen Fällen, die mir in den Sinn kommen, tendiere ich dazu, sie zu vermeiden.
Nur in SQL ...
Gespeicherte Prozedur-Ausgabeparameter sind nützlich.
Angenommen, Sie benötigen einen Wert zurück. Erstellst du #table, insert ... exec, wähle @var=". Oder verwenden Sie einen Ausgabeparameter?
Bei Clientaufrufen ist ein Ausgabeparameter viel schneller als die Verarbeitung eines Recordsets.
Die Verwendung von RETURN-Werten ist auf eine ganze Zahl mit Vorzeichen beschränkt.
Einfacher wiederzuverwenden (z. B. ein Sicherheits-Check-Helfer-Verfahren)
Bei Verwendung von beiden: recordsets = Daten, Ausgabeparameter = Status / Nachrichten / rowcount usw.
Die Recordset-Ausgabe gespeicherter Prozeduren kann nicht stark wie UDFs oder Clientcode
Sie können nicht immer eine UDF verwenden (zB Protokollierung während der Sicherheitsüberprüfung oben)
Solange Sie jedoch nicht denselben Parameter für Eingabe und Ausgabe verwenden, sind die Optionen bis zur vollständigen Änderung von SQL eingeschränkt. Ich habe einen Fall, in dem ich einen Parameter für In- und Out-Werte verwende, aber ich habe einen guten Grund.
Meine zwei Cent:
Ich stimme zu, dass Ausgangsparameter eine relevante Praxis sind. VBA wird oft von Leuten gewartet, die mit der Programmierung noch nicht vertraut sind. Wenn jemand, der Ihren Code verwaltet, nicht bemerkt, dass ein Parameter ByRef ist, könnten schwerwiegende logische Fehler auftreten. Auch neigt es dazu, das Paradigma Eigenschaft / Funktion / Sub zu brechen.
Ein weiterer Grund dafür, dass die Verwendung von out-Parametern eine schlechte Vorgehensweise ist, besteht darin, dass Sie, wenn Sie mehr als einen Wert zurückgeben müssen, diese Werte in einer Datenstruktur wie einer Klasse oder einem Benutzer haben sollten Definierter Typ.
Sie können jedoch einige Probleme lösen. VB5 (und daher VBA für Office 97) erlaubte nicht, dass eine Funktion ein Array zurückgibt. Dies bedeutet, dass alles, was ein Array zurückgibt oder verändert, dies über einen "out" -Parameter tun müsste. In VB6 wurde diese Fähigkeit hinzugefügt, aber VB6 zwingt weiterhin Array-Parameter als Referenz (um übermäßiges Kopieren im Speicher zu verhindern). Jetzt können Sie einen Wert von einer Funktion zurückgeben, die ein Array ändert. Aber es wird nur ein Haar langsam (wegen der Akrobatik hinter den Kulissen); Es kann auch Neulinge dazu verleiten, zu denken, dass die Array-Eingabe nicht verändert wird (was nur dann der Fall sein wird, wenn jemand es so strukturiert hat). So finde ich, dass wenn ich eine Funktion habe, die ein Array verändert, es Verwirrung reduziert, um nur ein Sub anstelle einer Funktion zu verwenden (und es wird auch ein kleines bisschen schneller sein).
Ein anderes mögliches Szenario wäre, wenn Sie Code pflegen und einen out-Wert hinzufügen möchten, ohne die Schnittstelle zu unterbrechen, können Sie einen optionalen out-Parameter hinzufügen und sicher sein, dass Sie keinen alten Code brechen werden. Es ist keine gute Übung, aber wenn jemand jetzt etwas wollen und Sie keine Zeit haben, es "richtig zu machen" und alles neu zu strukturieren, kann das eine nützliche Ergänzung zu Ihrer Toolbox sein.
Wenn Sie jedoch Dinge von Grund auf entwickeln und mehrere Werte zurückgeben müssen, sollten Sie folgendes beachten:
1. Aufbrechen der Funktion.
2. Rückgabe eines UDT.
3. Zurückgeben einer Klasse.
Ihre Meinung klingt vernünftig für mich.
Ein weiterer Nachteil von Ausgabeparametern ist der zusätzliche Code, der benötigt wird, um Ergebnisse von einer Funktion zu einer anderen zu übertragen. Sie müssen die Variablen deklarieren, die Funktion aufrufen, um ihre Werte abzurufen, und dann die Werte an eine andere Funktion übergeben. Sie können Funktionsaufrufe nicht nur verschachteln. Dies macht das Lesen von Code sehr zwingend, anstatt deklarativ.
C ++ 0x erhält Tupel, eine anonyme Struktur-ähnliche Sache, auf deren Mitglieder Sie per Index zugreifen. C ++ - Programmierer können mehrere Werte in einen dieser Werte packen und zurückgeben. Hat C # sowas? Kann es stattdessen ein Array zurückgeben? Aber ja Ausgangsparameter sind ein bisschen peinlich und unklar.