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";
}
War es hilfreich?

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.

Ref in Referenzvariable

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top