Übergeben Sie a, ref
wenn Sie das Objekt ändern möchten:
TestRef t = new TestRef();
t.Something = "Foo";
DoSomething(ref t);
void DoSomething(ref TestRef t)
{
t = new TestRef();
t.Something = "Not just a changed t, but a completely different TestRef object";
}
Bezieht t
sich nach dem Aufruf von DoSomething nicht auf das Original new TestRef
, sondern auf ein völlig anderes Objekt.
Dies kann auch nützlich sein, wenn Sie den Wert eines unveränderlichen Objekts ändern möchten, z string
. B. a . Sie können den Wert von a nach seiner string
Erstellung nicht mehr ändern . Mit a ref
können Sie jedoch eine Funktion erstellen, die die Zeichenfolge für eine andere mit einem anderen Wert ändert.
Bearbeiten: Wie andere Leute erwähnt haben. Es ist keine gute Idee, es zu verwenden, es ref
sei denn, es wird benötigt. Wenn Sie ref
der Methode die Freiheit geben, das Argument für etwas anderes zu ändern, müssen Aufrufer der Methode codiert werden, um sicherzustellen, dass sie diese Möglichkeit nutzen.
Wenn der Parametertyp ein Objekt ist, fungieren Objektvariablen immer als Verweise auf das Objekt. Dies bedeutet, dass Sie bei Verwendung des ref
Schlüsselworts einen Verweis auf einen Verweis haben. Auf diese Weise können Sie die im obigen Beispiel beschriebenen Schritte ausführen. Wenn der Parametertyp jedoch ein primitiver Wert ist (z. B. int
), wird der Wert des übergebenen Arguments nach der Rückgabe der Methode geändert, wenn dieser Parameter innerhalb der Methode zugewiesen wird:
int x = 1;
Change(ref x);
Debug.Assert(x == 5);
WillNotChange(x);
Debug.Assert(x == 5); // Note: x doesn't become 10
void Change(ref int x)
{
x = 5;
}
void WillNotChange(int x)
{
x = 10;
}
ref
an der Anrufstelle angeben ... wo sonst möchten Sie, dass es unterschieden wird? Die Semantik ist auch einigermaßen klar, muss aber sorgfältig ausgedrückt werden (anstatt "Objekte werden als Referenz übergeben", was die übliche Übervereinfachung ist).Wenn Sie in .NET einen Parameter an eine Methode übergeben, wird eine Kopie erstellt. In Werttypen bedeutet, dass alle Änderungen, die Sie am Wert vornehmen, im Methodenbereich liegen und beim Beenden der Methode verloren gehen.
Wenn Sie einen Referenztyp übergeben, wird auch eine Kopie erstellt, es handelt sich jedoch um eine Kopie einer Referenz, dh Sie haben jetzt ZWEI Referenzen im Speicher auf dasselbe Objekt. Wenn Sie also die Referenz zum Ändern des Objekts verwenden, wird es geändert. Wenn Sie jedoch die Referenz selbst ändern - wir müssen uns daran erinnern, dass es sich um eine Kopie handelt -, gehen alle Änderungen auch beim Beenden der Methode verloren.
Wie bereits erwähnt, ist eine Zuordnung eine Änderung der Referenz und geht somit verloren:
Die obigen Methoden ändern das ursprüngliche Objekt nicht.
Eine kleine Modifikation Ihres Beispiels
quelle
Da TestRef eine Klasse ist (die Referenzobjekte sind), können Sie den Inhalt in t ändern, ohne ihn als Referenz zu übergeben. Wenn Sie jedoch t als Referenz übergeben, kann TestRef ändern, worauf sich das ursprüngliche t bezieht. dh lassen Sie es auf ein anderes Objekt zeigen.
quelle
Mit können
ref
Sie schreiben:Und t wird nach Abschluss der Methode geändert.
quelle
Stellen Sie sich Variablen (z. B.
foo
) von Referenztypen (z. B.List<T>
) als Objektkennungen der Form "Objekt # 24601" vor. Angenommen, die Anweisungfoo = new List<int> {1,5,7,9};
bewirktfoo
, dass "Objekt # 24601" (eine Liste mit vier Elementen) enthalten ist. Dannfoo.Length
fragt der Aufruf das Objekt Nr. 24601 nach seiner Länge und antwortet mit 4, alsofoo.Length
gleich 4.Wenn
foo
es ohne Verwendung an eine Methode übergeben wirdref
, kann diese Methode Änderungen an Objekt # 24601 vornehmen. Infolge solcher Änderungen istfoo.Length
möglicherweise nicht mehr gleich 4. Die Methode selbst kann sich jedoch nicht ändernfoo
, da sie weiterhin "Objekt # 24601" enthält.Durch die Übergabe
foo
alsref
Parameter kann die aufgerufene Methode Änderungen nicht nur an Objekt Nr. 24601, sondern auch an sichfoo
selbst vornehmen . Die Methode erstellt möglicherweise ein neues Objekt # 8675309 und speichert einen Verweis darauf infoo
. In diesem Fallfoo
würde nicht mehr "Objekt # 24601", sondern "Objekt # 8675309" gespeichert.In der Praxis enthalten Variablen vom Referenztyp keine Zeichenfolgen der Form "Object # 8675309". Sie enthalten nicht einmal etwas, das sinnvoll in eine Zahl umgewandelt werden kann. Obwohl jede Variable vom Referenztyp ein Bitmuster enthält, gibt es keine feste Beziehung zwischen den in solchen Variablen gespeicherten Bitmustern und den von ihnen identifizierten Objekten. Es gibt keine Möglichkeit, dass Code Informationen aus einem Objekt oder einer Referenz darauf extrahieren und später bestimmen kann, ob eine andere Referenz dasselbe Objekt identifiziert, es sei denn, der Code enthielt oder wusste von einer Referenz, die das ursprüngliche Objekt identifizierte.
quelle
Das ist wie ein Zeiger auf einen Zeiger in C. In .NET vorbei dies ermöglicht es Ihnen zu ändern , was die ursprüngliche T bezieht sich auf, persönlich , obwohl ich denke , wenn Sie tun , dass in .NET Sie haben wahrscheinlich ein Design - Problem bekommen!
quelle
Indem Sie das
ref
Schlüsselwort mit Referenztypen verwenden, übergeben Sie effektiv eine Referenz an die Referenz. In vielerlei Hinsicht ist es dasselbe wie die Verwendung desout
Schlüsselworts, aber mit dem kleinen Unterschied, dass es keine Garantie gibt, dass die Methode demref
Parameter 'ed tatsächlich etwas zuweist.quelle
ref
ahmt (oder verhält sich) als globaler Bereich nur für zwei Bereiche nach:quelle
Wenn Sie jedoch einen Wert übergeben, sind die Dinge anders. Sie können die Übergabe eines Werts als Referenz erzwingen. Auf diese Weise können Sie beispielsweise eine Ganzzahl an eine Methode übergeben und die Ganzzahl in Ihrem Namen von der Methode ändern lassen.
quelle
Ref gibt an, ob die Funktion das Objekt selbst oder nur seinen Wert in die Hände bekommen kann.
Das Übergeben als Referenz ist nicht an eine Sprache gebunden; Es handelt sich um eine Parameterbindungsstrategie neben Wertübergabe, Namensübergabe, Bedarfsübergabe usw.
Eine Nebenbemerkung: Der Klassenname
TestRef
ist in diesem Zusammenhang eine schrecklich schlechte Wahl;).quelle