2010-06-27 3 views
18

Soweit ich feststellen kann, ist die einzige Verwendung für out Parameter, dass ein Aufrufer mehrere Rückgabewerte von einem einzigen Methodenaufruf erhalten kann. Wir können aber auch mehrere Ergebniswerte unter Verwendung der Parameter ref erhalten!In welchen Situationen sind "out" -Parameter nützlich (wo 'ref' stattdessen nicht verwendet werden könnte)?

Gibt es andere Situationen, in denen out Parameter nützlich sein könnten und wo wir ref Parameter stattdessen nicht verwenden könnten?

Vielen Dank.

+0

NB: Ich habe gerade [diese Antwort] (http://stackoverflow.com/questions/4102892/real-world-examples-where-c-out-parameters-are-useful/7220754#7220754) an Eine ähnliche Frage, bei der ich ein Szenario beschreibe, in dem ein out-Parameter für etwas anderes nützlich ist als die Rückgabe von mehr als einem Wert aus einer Methode. – stakx

Antwort

29

Ja - der Unterschied zwischen ref und out ist im Hinblick auf die eindeutige Zuordnung:

  • Ein out Parameter nicht haben, auf jeden Fall durch den Anrufer vor dem Methodenaufruf zugeordnet werden. Es muss definitiv in der Methode zugeordnet werden, bevor es normal zurückkehrt (d. H. Ohne Ausnahme). Die Variable ist dann eindeutig im Aufrufer nach dem Aufruf zugeordnet.

  • Ein ref Parameter muss vom Aufrufer vor dem Methodenaufruf eindeutig zugewiesen werden. Es nicht muss einen anderen Wert in der Methode zugewiesen werden.

Also nehmen wir an int.TryParse(string, out int) ändern wollte ref stattdessen zu verwenden. Normalerweise ist der Aufruf-Code sieht wie folgt aus:

int value; 
if (int.TryParse(text, out value)) 
{ 
    // Use value 
} 
else 
{ 
    // Do something else 
} 

Wenn wir nun ref verwendet, würden wir value Wert vor dem Aufruf geben, zum Beispiel:

int value = 0; 
if (int.TryParse(text, ref value)) 
{ 
    // Use value 
} 
else 
{ 
    // Do something else 
} 

Natürlich ist es kein riesige Unterschied - aber es gibt den falschen Eindruck. Wir geben einen Wert zu, den wir nie verwenden werden, und das ist nicht gut für die Lesbarkeit. Ein out Parameter zeigt an, dass ein Wert aus der Methode herauskommen wird (vorausgesetzt es gibt keine Ausnahme) und dass Sie keinen Wert haben müssen, um damit zu beginnen.

Einmal die Vorschläge, die ich für C# 5 gemacht habe (ich habe keine Ahnung, ob es übernommen wird oder nicht) ist, dass eine Methode mit einem out Parameter als eine Methode betrachtet werden kann, die ein Tupel zurückgibt von Werten. In Kombination mit einer besseren Unterstützung für Tupel, das würde bedeuten, wir so etwas tun könnte:

var (ok, value) = int.TryParse(text); 

In diesem Fall ok und value würden jeweils bool und int implizit eingegeben werden. Auf diese Weise ist klar, was in die Methode (text) und was herauskommt (zwei Informationen: ok und value).

, die einfach nicht zur Verfügung stehen würde, wenn int.TryParse stattdessen einen ref Parameter - wie der Compiler kann nicht wissen, ob es sich um den Anfangswert des ref Parameter tatsächlich Pflege geht.

+0

+1 - Ich mag die Idee eines Tupel-Ergebniswertes impliziert durch Out-Parameter. – Thomas

+1

@Thomas: Es ist nicht original - ich kniff es von F # :) –

+1

_ (Etwas off-topic:) _ Stimmen Sie mit Jon auf seine Anfrage für Tupel "Entpacken" (Whatdoyoucallit). Ich verstehe immer noch nicht, warum so viel Aufhebens um die Unterstützung von Tupeln in .NET/C# 4.0 gemacht wurde - und dass sie anscheinend sogar die CLR dafür anpassen mussten -, während gleichzeitig dieses sehr nützliche Feature übrig blieb aus. Sorgt dafür, dass der "Tuple" -Typ sehr trivial aussieht, wenn nicht sogar fast nutzlos. – stakx

2

Ein out Parameter ist nützlich, wenn Sie mehrere Ergebniswerte aus einer Methode wollen. Technisch könnten Sie einen ref Parameter verwenden, um das gleiche Ziel zu erreichen, aber ein out Parameter macht eine wesentlich bessere Arbeit bei der Förderabsicht. Wenn Sie ref verwenden, ist es nicht klar, warum Sie dies tun, anstatt out zu verwenden oder das Funktionsergebnis zu verwenden. Vermutlich beabsichtigen Sie, den übergebenen Wert zu ändern, aber warum Sie ihn ändern, ist nicht einfach aus der Funktionssignatur ersichtlich.

8

Sie auf Parameter auf diese Weise aussehen:

  • normalen Parameter sind in Parameter:
    Ein Wert kann in die Funktion durch eine solche Parameter gehen; Daher muss es initialisiert werden.

  • ref Parameter sind in-out Parameter:
    einen Wert in eine und aus einer Funktion durch einen solchen Parameter gehen kann. Wegen ersterer muss es auch initialisiert werden.

  • out Parameter sind out Parameter:
    Ein Wert soll nur aus einer Funktion durch einen solchen Parameter kommen; Daher muss es nicht initialisiert werden.

kam ich mit dieser Art und Weise aus ref/out Parametern bei der Suche von Microsoft COM-Technologie durch das Studium. IDL (Schnittstellenbeschreibungssprache) wird verwendet, um COM-Komponentenschnittstellen zu beschreiben, und mit IDL werden Parameter mit in, out und inout Deklaratoren erweitert. Ich vermute, dass .NET und C# diese Deklaratoren teilweise von COM geerbt haben, wenn auch mit etwas anderen Namen (ref anstelle von inout).

Mit COM werden out Parameter häufig verwendet, um den tatsächlichen Rückgabewert einer Schnittstellenmethode abzurufen, da der "echte" Rückgabewert oft bereits für die Rückgabe eines Erfolgs-/Fehlercodes HRESULT verwendet wird.

Mit.NET, ich denke, out Parameter haben weit weniger Bedeutung, auch in Fällen, in denen Sie mehrere Werte von einer Methode (Sie könnten komplexe Objekte oder Tuple s in diesen Situationen zurückgeben) zurückgeben möchten.

2

denke ich, ein gutes Beispiel ist int.TryParse()

http://msdn.microsoft.com/en-us/library/f02979c7.aspx

Der Hauptgrund, dass aus besser als ref ist, dass Sie einen Dummy-Wert zuweisen müssen, um nicht die Rückgabe var vor dem Aufruf (auch implizit).

So aus sagt Ihnen, und der Compiler: "Diese var wird innerhalb der Methode zugeordnet werden. Und die var der Anfangswert, wenn überhaupt, wird nicht einmal angesehen werden."

0

wesentliche Unterschied zwischen den beiden ist, dass, wenn wir ref verwenden dann müssen wir dies vor Aufruf initialisieren und es ist optional, dass wir einen Mehrwert für unsere ref Variable in unserer Methode zuweisen.

Aber für aus Methoden müssen wir sie nicht explizit initialisieren, aber in unserer Methode müssen wir ihr einen Wert zuweisen, andernfalls werden sie Kompilierzeit Fehler generieren.

Verwandte Themen