Bei der Verwendung in vs ref vs aus
Jemand fragte mich, den anderen Tag, wenn Sie sollten den parameter-Schlüsselwort out
statt ref
. Während ich (glaube ich) verstehen den Unterschied zwischen der ref
und out
keywords (wurde vor der Frage) und die beste Erklärung scheint zu sein, dass ref
== in
und out
, was sind einige (hypothetische oder code -) Beispiele, wo ich sollte immer out
und nicht ref
.
Seit ref
ist mehr allgemein, warum haben Sie jemals benutzen wollen out
? Ist es nur syntaktischer Zucker?
- Eine variable übergeben mit
out
kann nicht gelesen werden, bevor Sie zugewiesen wird.ref
hat diese Einschränkung nicht. Es gibt also das. - In kurzen,
ref
ist für die in - /out -, währendout
ist ein out-parameter nur. - Was genau bekommst du denn nicht?
- Auch
out
- Variablen zugewiesen werden, die in der Funktion. - Danke Corey. Aber ich habe schon nicht. Mein Punkt ist, dass das, was ist der Vorteil dieser. Eigentlich brauche ich ein Beispiel, das zeigt ein Szenario, wo wir können ref-parameter zu erreichen, eine Funktion, die nicht erreicht werden kann durch die Verwendung der out-parameter und Umgekehrt.
- Jungs Corey, Tim S, tnw, Dan Hunex versuchen Sie nicht zu unterschätzen, eine person.
- ich bin nicht nehmen Sie es als persönlichen. Tatsächlich, die Sie Jungs haben nicht versuchen zu verstehen, was ich bat in meiner Frage, und ich mochte es nicht. zneak ist ein Kerl, der tatsächlich bemühen sich darum, mir die Frage zu beantworten. Und ich bin wirklich froh, dass ich bekam Antwort auf meine Frage. Alles andere spielt keine Rolle. Das ist es.
- ich denke nicht so. Zuerst habe ich gegoogelt, diese Frage, wenn ich bekam keine richtige Antwort, nur dann Frage ich hier und ich dachte, dies ist der richtige Ort, um die richtige Antwort. Aber Sie sagte, es ist off-topic, was wiederum nicht sinnvoll ist.
- Lesen Sie die off-topic in der Nähe Stimmen: "Fragen Fragen zum code muss nachweisen, dass eine minimale Verständnis von dem problem. Fügen Sie versucht, Lösungen, warum Sie nicht arbeiten, und die erwarteten Ergebnisse." Wenn Sie nicht wissen, Wann genau Sie zu verwenden, eine über der anderen, haben Sie nicht, Lesen Sie die Dokumentation gründlich genug.
- lassen Sie uns weiter, diese Diskussion im chat
- möglich, Duplikat der What ist der Unterschied zwischen den 'ref' und 'out' keywords?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sollten Sie verwenden
out
es sei denn, Sie müssenref
.Macht es einen großen Unterschied, wenn die Daten umgewandelt werden, z.B. um einen anderen Prozess, das kann teuer werden. So möchten Sie vermeiden, marshalling der anfängliche Wert, wenn die Methode nicht nutzen es.
Darüber hinaus zeigt es auch die Leser der Deklaration oder den Aufruf, ob der erste Wert ist relevant (und möglicherweise erhalten), oder weggeworfen.
Als ein kleiner Unterschied, ein out-parameter muss nicht initialisiert werden.
Beispiel für
out
:wo GetBothNames ist eine Methode zum abrufen der zwei Werte atomar, wird die Methode nicht ändern, das Verhalten, was a und b sind. Wenn der Aufruf geht an einen server in Hawaii, kopieren die ursprünglichen Werte von hier nach Hawaii ist eine Verschwendung von Bandbreite. Ein ähnliches snippet mit ref:
könnte Leser verwirren, weil es aussieht wie die ersten Werte von a und b relevant sind (obwohl der Namen der Methode geben würde, Sie sind nicht).
Beispiel für
ref
:Hier der erste Wert ist relevant für die Methode.
ref
für Standard-Werte.out
parameter, die aufrufende Methode ist erforderlich einen Wert zuweisen, bevor die Methode zurückgibt. Sie nicht müssen, etwas zu tun mit einem ref-parameter.Verwenden aus, um anzuzeigen, dass der parameter nicht verwendet wird, nur das einstellen. Dies hilft dem Anrufer zu verstehen, dass Sie immer die Initialisierung der parameter.
Ebenfalls, ref und out sind nicht nur für value-Typen. Sie können auch zurückgesetzt, das Objekt, das eine Referenz Typ Referenzierung innerhalb einer Methode.
out
Parameter behandelt werden als nicht zugeordnet auf den Eintritt in die Funktion. Sie werden nicht in der Lage sein, um deren Wert zu überprüfen, bis Sie die ersten definitiv zugewiesen werden einige Wert-es gibt keinen Weg überhaupt, um den Wert des Parameters hatte, als die Funktion aufgerufen wurde.Du bist, dass richtig ist, semantisch,
ref
bietet sowohl für "in" und "out" - Funktionalität, in der Erwägung, dassout
nur "out" - Funktion. Es gibt einige Dinge zu beachten:out
erfordert, dass die Methode der Annahme der parameter MUSS, an einem gewissen Punkt, bevor er, einen Wert zuweisen, der der Variablen zugewiesen wird. Sie finden dieses Muster in einige der Schlüssel/Wert-Daten-Speicher-Klassen, wieDictionary<K,V>
, wo Sie Funktionen wieTryGetValue
. Diese Funktion nimmt einout
parameter, der das hält, was der Wert sein wird, wenn abgerufen. Wäre es nicht sinnvoll, wenn der Aufrufer einen Wert übergeben in diese Funktion, soout
wird verwendet, um zu garantieren, dass einige Wert wird in der Variablen nach dem Aufruf, auch wenn es nicht "real" - Daten (im Falle vonTryGetValue
wo der Schlüssel nicht vorhanden ist).out
undref
Parameter sind gemarshallt anders beim Umgang mit interop-codeAuch, wie nebenbei, es ist wichtig zu beachten, dass, während die Referenz-Typen und Wert-Typen unterscheiden sich in der Art Ihrer Wert, jede variable in Ihrer Anwendung Punkte zu einem Ort der Erinnerung, hat einen Wert, auch für Referenztypen. Es passiert einfach, dass mit Referenz-Typen, die enthaltenen Wert in diesem Ort der Erinnerung ist anderen Speicher. Wenn Sie die übergabe von Werten an eine Funktion (oder jede andere variable Zuordnung), der Wert der variable wird kopiert und in die andere variable. Für value-Typen, das heißt, dass der gesamte Inhalt der Typ kopiert. Für Referenz-Typen, das heißt, die Speicherstelle kopiert wird. So oder so, es funktioniert erstellen Sie eine Kopie der enthaltenen Daten in der Variablen. Die einzige wirkliche Bedeutung, die dieser hält, beschäftigt sich mit der Abtretung Semantik; wenn die Zuweisung einer variable oder als Wert übergeben werden (Standardeinstellung), wenn eine neue Aufgabe wird auf die ursprüngliche (oder neuer) variable, es hat keinen Einfluss auf die anderen Variablen. Im Fall von Referenz-Typen, ja, änderungen an der Instanz sind auf beiden Seiten, aber das ist, weil die eigentliche variable ist nur ein Zeiger auf einen anderen Speicherbereich; der Inhalt der variable--die Speicher Lage--nicht wirklich ändern.
Vorbei mit
ref
Schlüsselwort sagt, dass sowohl die ursprüngliche variable und der parameter der Funktion wird eigentlich auf die gleiche Speicherstelle. Dies wiederum wirkt sich nur auf die Zuordnung der Semantik. Wenn ein neuer Wert wird zugewiesen, um eine der Variablen, und dann, weil die anderen Punkte auf der gleichen Speicherstelle der neue Wert wird reflektiert, auf der anderen Seite.TryGetValue
verwenden würderef
und nichtout
ausdrücklich im Falle der nicht der Suche nach dem Schlüssel.Kommt es auf die compile-Kontext (Siehe Beispiel unten).
out
undref
beide bezeichnen die Variablen-übergabe per Referenz, nochref
erfordert die Variablen initialisiert werden, bevor Sie weitergegeben werden, was ein wichtiger Unterschied in den Kontext des Marshalling (Interop: UmanagedToManagedTransition oder Umgekehrt)MSDN warnt:
Do not confuse the concept of passing by reference with the concept of reference types. The two concepts are not the same. A method parameter can be modified by ref regardless of whether it is a value type or a reference type. There is no boxing of a value type when it is passed by reference.
Aus der offiziellen MSDN-Dokumentation:
aus
:The out keyword causes arguments to be passed by reference. This is similar to the ref keyword, except that ref requires that the variable be initialized before being passed
ref
:The ref keyword causes an argument to be passed by reference, not by value. The effect of passing by reference is that any change to the parameter in the method is reflected in the underlying argument variable in the calling method. The value of a reference parameter is always the same as the value of the underlying argument variable.
Wir können bestätigen, dass die out und ref sind in der Tat die gleiche, wenn das argument zugewiesen bekommt:
CIL Beispiel:
Betrachten Sie das folgende Beispiel
in CIL, die Anweisungen der
myfuncOut
undmyfuncRef
identisch sind, wie erwartet.nop: keine operation, ldloc: laden, lokal, stloc: Stapel lokale, ldarg: Last argument bs.s: Zweig zum Ziel....
(Siehe: Liste der CIL-Anweisungen )
Im folgenden sind einige Hinweise, die ich zog aus dieser codeproject Artikel über C# Aus Vs Ref
Wenn Sie eine visual person sind, dann finden Sie dieses yourtube-video, das zeigt den Unterschied praktisch https://www.youtube.com/watch?v=lYdcY5zulXA
Unten stehende Bild zeigt die Unterschiede mehr optisch
one-way
,two-way
Bedingungen könnte missbraucht werden, hier. Sie sind beide zwei-Wege, aber Ihr konzeptionelles Verhalten unterscheidet sich auf Parameter, die Referenzen und WerteMüssen Sie
ref
wenn Sie planen, Lesen und schreiben der parameter. Sie benötigenout
wenn Sie nur schreiben wollen. Im Endeffektout
ist für, wenn Sie brauchen mehr als einen Wert zurückgeben, oder wenn Sie nicht wollen, verwenden Sie die normale return-Mechanismus für die Ausgabe (aber das sollte selten sein).Gibt es die Sprache der mechanik, die helfen, diese use-cases.
Ref
Parameter müssen initialisiert werden, bevor Sie an eine Methode übergeben (die Betonung auf die Tatsache, dass Sie lese- /Schreibzugriff), undout
Parameter können nicht gelesen werden, bevor Sie zugeordnet sind, einen Wert, und sind garantiert, um zu haben, geschrieben worden ist, am Ende der Methode (die Betonung auf die Tatsache, dass Sie nur schreiben). Bei Verstössen gegen diese Prinzipien Ergebnisse in einem compile-time-Fehler.Beispielsweise
int.TryParse
gibt einebool
und akzeptiert einout int
parameter:Dies ist ein klares Beispiel für eine situation, wo Sie brauchen, um die Ausgabe von zwei Werten: das numerische Ergebnis ist und ob die Konvertierung erfolgreich war oder nicht. Die Autoren der CLR, entschied Sie sich für
out
hier, da Sie nicht kümmern, was dieint
gewesen sein könnte, bevor.Für
ref
kann man sichVerriegelt.Schrittweite
:Interlocked.Increment
atomar inkrementiert den Wert vonx
. Da müssen Sie Lesenx
zu erhöhen, ist dies eine situation, woref
mehr angemessen ist. Sie völlig gleichgültig, wasx
war, bevor es verabschiedet wurde, umIncrement
.In der nächsten version von C# wird es sogar möglich sein, deklarieren Sie die variable in
out
Parameter, indem noch mehr Wert auf Ihre Ausgabe-nur Natur:out
Parameter haben nicht unbedingt initialisiert wurde, so dass der compiler nicht zulassen, Sie Lesen aus einerout
parameter, bis du geschrieben hast etwas, um es.nameOut
in Ihremif
Aussage, denn es war nicht zugewiesen, was vor.out
ist mehr Einschränkung-version vonref
.In einer Methode, die Körper, die Sie zuordnen müssen alle
out
Parameter vor dem verlassen der Methode.Auch Werte zugewiesen werden, um ein
out
parameter wird ignoriert, währendref
verlangt, dass Sie zugeordnet werden.So
out
können Sie tun:wo
ref
erfordern würde und b zugeordnet werden.out
ist das weniger eingeschränkte version.ref
hat "Voraussetzung: die variable ist definitiv zugewiesen, Postcondition: variable ist definitiv zugewiesen", währendout
hat nur `Postcondition: variable ist definitiv zugewiesen". (Und, wie erwartet, mehr ist es erforderlich, eine Implementierung der Funktion, die mit weniger Voraussetzungen), Wie es klingt:
aus = nur initialisieren/fill ein parameter (der parameter muss leer sein) zurück aus plain
ref = Referenz -, standard-parameter (vielleicht mit Wert), aber die Funktion kann modifizieren es.
Können Sie die
out
kontextbezogene Schlüsselwort in zwei Kontexten (jedes ist ein link zu ausführlichen Informationen), die als parameter modifier oder generischen Typ-parameter-Deklarationen in interfaces und Delegaten. Dieses Thema beschreibt die parameter modifier, aber Sie können sehen, dass dieses andere Thema für Informationen, die auf den generischen Typ-parameter-Deklarationen.Den
out
- Schlüsselwort bewirkt, dass Argumente als Verweis übergeben werden. Das ist wie dieref
Schlüsselwort, außer dassref
erfordert, dass die variable initialisiert werden, bevor es übergeben wird. Die Verwendung einerout
parameter, sowohl die Methode als definition und die aufrufende Methode muss explizit dieout
Schlüsselwort. Zum Beispiel:C#
Obwohl die Variablen übergeben
out
Argumente nicht initialisiert werden, bevor Sie weitergegeben werden, in der die aufgerufene Methode ist erforderlich, um einen Wert zuweisen, bevor die Methode zurückgibt.Obwohl die
ref
undout
keywords zu unterschiedlichen Laufzeitverhalten, werden Sie nicht als Teil der Signatur der Methode zur compile-Zeit. Daher können keine Methoden überladen werden, wenn der einzige Unterschied ist, dass man die Methode nimmt einenref
argument, der andere nimmt eineout
argument. Der folgende code zum Beispiel wird nicht kompilieren:C#
Überlastung getan werden kann, jedoch, wenn eine Methode nimmt eine
ref
oderout
argument und die andere nutzt weder, wie diese:C#
Eigenschaften sind keine Variablen und können daher nicht weitergegeben werden, wie
out
Parameter.Weitere Informationen zum übergeben von arrays finden Sie unter Übergeben von Arrays Mithilfe von
ref
undout
(C# - Programmierhandbuch).Können Sie nicht verwenden, die
ref
undout
keywords für die folgenden Arten von Methoden:Beispiel
Erklären, eine
out
Methode ist nützlich, wenn Sie eine Methode mehrere Werte zurückgeben. Das folgende Beispiel verwendetout
zurück drei Variablen mit einem einzigen Methodenaufruf. Beachten Sie, dass das Dritte argument wird mit dem Wert null. Dies ermöglicht Methoden, Rückgabe von Werten ist Optional möglich.C#
Genau zu klären, auf OP ' s Kommentar, dass die Verwendung auf ref und out ist eine "Referenz auf einen Wert eingeben oder struct deklariert, die außerhalb der Methode", das bereits gegründet wurde, in die falsche.
Betrachten Sie die Verwendung von ref auf ein StringBuilder-Objekt, das einen Verweis geben:
Als adaptiert zu diesem:
Wie zu verwenden
in
oderout
oderref
in C#?C#
haben die gleiche Funktionalität, aber mit einigen Grenzen.in
Argumente können nicht geändert werden, die von der aufgerufenen Methode.ref
Argumente geändert werden kann.ref
muss initialisiert werden, bevor Sie verwendet werden um Anrufer Sie können gelesen und aktualisiert werden in der Methode.out
Argumente müssen geändert werden, indem der Anrufer.out
Argumente initialisiert werden muss in der Methodein
Argumente müssen initialisiert werden, bevor Sie weitergegeben werden, in einer Methode aufrufen. Jedoch, in der die aufgerufene Methode kann nicht zuordnen einen Wert, oder ändern Sie das argument.Können Sie nicht verwenden, die
in
,ref
, undout
keywords für die folgenden Arten von Methoden:async
modifier.yield return
oderyield break
- Anweisung.Argument übergeben als ref muss initialisiert werden, bevor wir auf die Methode, während out-parameter nicht initialisiert ist, bevor die übergabe an eine Methode.
Andere wissen zu lassen, dass die variable initialisiert wird, wenn es zurückkehrt, aus der genannten Methode!
Wie oben erwähnt:
"für ein out-parameter, der aufrufenden Methode erforderlich ist, einen Wert zuweisen, bevor die Methode gibt."
Beispiel:
Grundsätzlich beide
ref
undout
für die übergabe von Objekt/Wert zwischen MethodenDem out-Schlüsselwort bewirkt, dass Argumente als Verweis übergeben werden. Das ist wie das ref-Schlüsselwort, außer, dass der ref verlangt, dass die variable initialisiert werden, bevor es übergeben wird.
out
: Argument ist nicht initialisiert und es muss initialisiert werden, in der Methoderef
: Argument ist bereits initialisiert und es können gelesen und aktualisiert werden in der Methode.Was ist die Verwendung von "ref" für Referenz-Typen ?
Können Sie ändern die angegebene Referenz auf eine andere Instanz.
Wussten Sie schon?
Obwohl der ref-und out-keywords zu unterschiedlichen Laufzeitverhalten, werden Sie nicht als Teil der Signatur der Methode zur compile-Zeit. Daher können keine Methoden überladen werden, wenn der einzige Unterschied ist, dass eine Methode ein ref-argument und der andere nimmt ein out-argument.
Können Sie nicht mithilfe des ref-und out-keywords für die folgenden Arten von Methoden:
Eigenschaften sind keine Variablen und können daher nicht weitergegeben werden als out-Parameter.
Zusätzliche Notizen zu C# 7:
In C# 7 es gibt keine Notwendigkeit, predeclare Variablen mit sich. So ein code wie dieser:
Kann wie folgt geschrieben werden:
Quelle: Was ist neu in C# 7.
Es sollte angemerkt werden, dass
in
ist ein gültiges Schlüsselwort als der C# ver-7.2: