Was ist die Verwendung von „ref“ Referenz-Typ-Variablen in C #?
-
12-09-2019 - |
Frage
Ich verstehe, dass wenn ich einen Wert-Typen (int
, struct
, etc.) als Parameter (ohne ref
Schlüsselwort), eine Kopie dieser Variable übergebe an die Methode übergeben wird, aber wenn ich das ref
Schlüsselwort einer Verweis auf diese Variable übergeben wird, ist nicht neu.
Aber mit Referenztypen wie Klassen, auch ohne das ref
Schlüsselwort, wird ein Verweis auf die Methode übergibt, keine Kopie. Also, was ist die Verwendung des ref
Schlüsselwort mit Referenztypen?
Nehmen Sie zum Beispiel:
var x = new Foo();
Was ist der Unterschied zwischen den folgenden?
void Bar(Foo y) {
y.Name = "2";
}
und
void Bar(ref Foo y) {
y.Name = "2";
}
Lösung
Sie können was foo
Punkte ändern y
zu verwenden:
Foo foo = new Foo("1");
void Bar(ref Foo y)
{
y = new Foo("2");
}
Bar(ref foo);
// foo.Name == "2"
Andere Tipps
Es gibt Fälle, in denen Sie den aktuellen Verweis ändern mögen und nicht das anvisierten Objekt:
void Swap<T>(ref T x, ref T y) {
T t = x;
x = y;
y = t;
}
var test = new[] { "0", "1" };
Swap(ref test[0], ref test[1]);
Jon Skeet einen großen Artikel über Parameter in C # übergeben. Es wird ausführlich eindeutig das genaue Verhalten und die Verwendung von Parametern nach Wert, durch Verweis (ref
) vorbei und durch den Ausgang (out
).
Hier ist ein wichtiges Zitat von dieser Seite in Bezug auf ref
Parameter:
Referenzparameter nicht passieren die Werte der Variablen in der verwendeten Funktionsmemberaufruf - sie verwenden die Variablen selbst. Eher, als einen neuen Speicherort für die Schaffung die Variable in dem Funktionselement Erklärung, die gleiche Speicherstelle ist, so dass der Wert der Variablen verwendet, in dem Funktionselement und der Wert des Referenzparameter wird immer gleich sein. Referenzparameter müssen ref der Modifikator als Teil sowohl der Erklärung und der Aufruf - das bedeutet, es ist immer klar, wenn Sie etwas durch Verweis übergeben.
erklärt Sehr schön hier: http://msdn.microsoft.com/en-us/library/s6938f28.aspx
Auszug aus dem Artikel:
Eine Variable eines Referenztyp hat seine Daten nicht direkt zu enthalten; es enthält einen Verweis auf seine Daten. Wenn übergeben Sie eine Referenz-Typ Parameter nach Wert, ist es möglich, die Daten, auf die sich ändern die Referenz, wie der Wert eines Klassenmitglied. Aber du kann nicht den Wert der sich Referenz ändern; Das heißt, dass Sie nicht verwenden den gleichen Referenzspeicher für eine neue Klasse zuweisen und sie haben bestehen bleiben außerhalb des Blocks. Um das zu tun, übergeben Sie die Parameter der Verwendung ref oder out-Schlüsselwort.
Wenn Sie eine Referenz-Typ mit dem Schlüsselwort ref geben, übergeben Sie die Referenz Bezug genommen wird, und die Methode, die Sie einen neuen Wert an den Parameter aufrufen können zuweisen. Diese Änderung wird an den rufenden Umfang ausbreiten. Ohne ref wird die Referenz Wert übergibt, und dies nicht geschieht.
C # hat auch das ‚out‘ Schlüsselwort, das viel wie ref ist, mit der Ausnahme, dass mit ‚ref‘, Argumente vor dem Aufruf die Methode initialisiert werden muss, und mit ‚out‘ Sie müssen einen Wert in dem Empfangsverfahren zugeordnet werden.
Es ermöglicht Ihnen, die als Referenz übergeben in ändern. Z.
void Bar()
{
var y = new Foo();
Baz(ref y);
}
void Baz(ref Foo y)
{
y.Name = "2";
// Overwrite the reference
y = new Foo();
}
Sie können auch aus , wenn Sie über den Verweis in vergangen ist es egal:
void Bar()
{
var y = new Foo();
Baz(out y);
}
void Baz(out Foo y)
{
// Return a new reference
y = new Foo();
}
Eine weitere Reihe von Code
class O
{
public int prop = 0;
}
class Program
{
static void Main(string[] args)
{
O o1 = new O();
o1.prop = 1;
O o2 = new O();
o2.prop = 2;
o1modifier(o1);
o2modifier(ref o2);
Console.WriteLine("1 : " + o1.prop.ToString());
Console.WriteLine("2 : " + o2.prop.ToString());
Console.ReadLine();
}
static void o1modifier(O o)
{
o = new O();
o.prop = 3;
}
static void o2modifier(ref O o)
{
o = new O();
o.prop = 4;
}
}
Zusätzlich zu den vorhandenen Antworten:
Wie Sie für den Unterschied der zwei Methoden gefragt: Es gibt keine Co (ntra) Varianz bei ref
oder out
mit:
class Foo { }
class FooBar : Foo { }
static void Bar(Foo foo) { }
static void Bar(ref Foo foo) { foo = new Foo(); }
void Main()
{
Foo foo = null;
Bar(foo); // OK
Bar(ref foo); // OK
FooBar fooBar = null;
Bar(fooBar); // OK (covariance)
Bar(ref fooBar); // compile time error
}
Ein Parameter in einem Verfahren scheint eine Kopie immer zu vorbei, die Frage eine Kopie dessen, was ist. Eine Kopie wird durch einen Kopierkonstruktor für ein Objekt durchgeführt und da alle Variablen Objekt in C # ist, glaube ich, in diesem Fall für alle von ihnen. Variablen (Objekte) sind wie Menschen bei einigen Adressen leben. Entweder wir ändern, um die Menschen an diesen Adressen leben oder wir können mehr Verweise auf die Menschen schaffen auf diese Adressen im Telefonbuch leben (machen flache Kopien). Also, mehr als eine Kennung kann auf die gleiche Adresse verweisen. Referenztypen wünschen mehr Platz, so dass im Gegensatz zu Werttypen, die direkt durch einen Pfeil auf ihre Kennung in dem Stapel verbunden sind, sie Wert haben für eine andere Adresse im Heap (ein größerer Raum zu wohnen). Dieser Raum muss von der Halde genommen werden.
Werttyp: Indentifier (enthält den Wert = Adresse des Stapelwert) ----> Wert von Werttyp
Art der Veröffentlichung: Identifier (enthält Wert = Adresse des Stapelwert) ----> (enthält Wert = Adresse des Heap-Wert) ----> Heap-Wert (am häufigsten enthält Adressen auf andere Werte), weitere Pfeile in unterschiedlichen Richtungen vorstellen Festhalten an Array [0], Array [1], array [2]
Der einzige Weg, um einen Wert zu ändern ist, um die Pfeilen zu folgen. Wenn ein Pfeil geht verloren / in der Art und Weise verändert hat, ist der Wert nicht erreichbar.
Referenzvariablen tragen die Adresse von einem Ort zum anderen so auf ihnen jede updation an jedem Ort auf allen Orten reflektieren dann, was die Verwendung von REF ist. Referenzgröße (405) ist gut, bis kein neuer Speicher auf die Bezugsgröße in der Methode übergibt zugeordnet ist.
Sobald neuer Speicher zuweisen (410) dann die Wertänderung auf diesem Objekt (408) nicht überall widerspiegelt. Zu diesem ref kommt. Ref ist Referenz so Referenz, wenn neue Speicher es zu wissen, zuteilen, weil es deshalb zu dieser Stelle zeigt der Wert von allen geteilt werden kann. Sie können das Bild für mehr clearity sehen.