Warum ist die Liste übergeben wird, ohne ref, um eine Funktion handeln, wie übergeben mit ref?
Wenn ich nicht diese schrecklich falsch, dieses Verhalten ist merkwürdig für mich. Anstatt zu erklären, poste ich ein Beispiel-code unten, und sagen Sie mir bitte warum bekomme ich Ausgang x und nicht y.
private void button1_Click(object sender, EventArgs e)
{
List<int> l = new List<int>() { 1, 2, 3 };
Fuss(l);
MessageBox.Show(l.Count.ToString());
}
private void Fuss(List<int> l)
{
l.Add(4);
l.Add(5);
}
Ausgabe sollte, angenommen ich würde 3 sein. Aber ich bekomme als Ausgabe 5. Ich verstehe die Ausgabe kann 5 sein, wenn ich dies tun:
private void button1_Click(object sender, EventArgs e)
{
List<int> l = new List<int>() { 1, 2, 3 };
Fuss(ref l);
MessageBox.Show(l.Count.ToString());
}
private void Fuss(ref List<int> l)
{
l.Add(4);
l.Add(5);
}
Sie sollten wahrscheinlich Lesen Sie auch Jon Skeet Parameterübergabe in C#.
InformationsquelleAutor nawfal | 2011-09-06
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wirken Sie nicht wie seine passed by ref.
Versuchen Sie es. Merkst du den Unterschied?
Können Sie nur ändern, den Inhalt der Liste (oder eine Referenz-Typ) wenn Sie übergeben, ohne ein ref (, weil wie schon andere gesagt haben, übergeben Sie einen Verweis auf das Objekt auf dem heap, und somit das gleiche "memory").
Allerdings kann man nicht ändern "Liste", "Liste" eine variable ist, die Punkte auf ein Objekt vom Typ Liste. Sie kann sich nur ändern "Liste", wenn Sie es passieren Referenz (um es irgendwo anders). Sie erhalten eine Kopie der Referenz, die, wenn verändert, können nur beobachtet werden, innerhalb Ihrer Methode.
InformationsquelleAutor
Parameter werden als Wert übergeben in C#, es sei denn, Sie sind gekennzeichnet mit dem
ref
oderout
Modifikatoren. Für Referenz-Typen, dies bedeutet, dass die Referenz wird als Wert übergeben. DaherFuss
,l
ist auf der gleichen Instanz vonList<int>
als seine Anrufer. Daher werden alle änderungen zu dieser Instanz vonList<int>
zu sehen sein wird der Anrufer.Nun, wenn Sie markieren Sie den parameter
l
mitref
oderout
, dann wird der parameter als Verweis übergeben wird. Was dies bedeutet ist, dass inFuss
,l
ist ein alias für den Speicherort verwendet, die als parameter an die Methode aufrufen. Um klar zu sein:genannt
Nun, in
Fuss
,l
ist ein alias fürlist
. Insbesondere, wenn Sie zuweisen eine neue Instanz vonList<int>
zul
Anrufer sehen, dass neue Instanz der Variablen zugewiesenlist
als gut. Insbesondere, wenn Sie sagen,dann die Anrufer sehen jetzt eine Liste mit einem element. Aber wenn Sie sagen,
- und call-by -
dann der Anrufer noch sehen
list
als drei Elemente.Klar?
l
ist, wird es nicht bekommen, spiegelt sich in den Anrufer. Aber wie ist es immer wider in mein problem habe ich gestellt ohne ref?Ich denke, @Steven 's Antwort klärt Ihre Antwort für mich. Das ist ohne ref ich ändern kann, den Inhalt der Liste, aber nicht die Liste selbst! Mit ref-beides kann ich, so scheint es.
Im zweiten Fall werden sowohl der angerufene und der Anrufer beziehen sich auf die gleiche Instanz von
List<int>
, so natürlich Sie sehen die änderungen. Im ersten Fall werden sowohl der angerufene und der Anrufer mit dem gleichen Speicherort. Es ist also nicht nur, dass Sie beide das gleiche sehenList<int>
ist, aber beide verändern die Instanz vonList<int>
einander anschaut!Ich Verstand, was Sie sagen. Ein großer Dank. Aber ich bekam die Stelle klarer aus FishBasketGordo und Steven. Lassen Sie mich markieren Sie Ihre. Zusammen haben Sie drei machten die Sache klarer für mich.
InformationsquelleAutor
Den Unterschied zwischen ref und non-ref für Referenz-Typen wie Liste, ist nicht, ob Sie übergeben eine Referenz (das passiert immer), aber ob das Referenz kann geändert werden. Versuchen Sie die folgenden
und du wirst sehen, der Graf ist 2, weil die Funktion nicht nur manipuliert die original-Liste, sondern die Referenz selbst.
InformationsquelleAutor
ByRef und ByVal gelten nur für value-Typen, keine Referenztypen, die immer weitergegeben, als wären Sie "byref" übergeben werden.
Wenn Sie brauchen, um zu ändern, eine Liste diskret, verwenden Sie die ".ToList ()" - Funktion, und erhalten Sie einen Klon Ihrer Liste.
Halten Sie im Verstand, wenn Ihre Liste enthält die Referenz-Typen, Ihre "neue" Liste enthält Zeiger auf die gleichen Objekte, die Ihre ursprüngliche Liste hat.
Darüber hinaus können Sie auch Sie einen .clone () - Methode
InformationsquelleAutor
Listen sind bereits Referenztypen, so dass, wenn Sie übergeben Sie an eine Methode übergeben Sie eine Referenz. Alle
Add
anrufen wirkt sich auf die Liste der Anrufer.Übergabe eines
List<T>
durchref
verhält sich im wesentlichen wie an einem double-Zeiger auf die Liste. Hier ist eine illustration:InformationsquelleAutor
Eine variable, ein parameter oder Feld vom Typ "Liste", oder jede andere Typ der Referenz, nicht wirklich eine Liste (oder ein Objekt einer anderen Klasse). Stattdessen wird es etwas wie "Object ID #29115" (nicht wie eine tatsächliche Zeichenfolge, natürlich, aber eine Kombination von bits, die bedeutet im wesentlichen, dass). Anderswo, das system muss eine indizierte Auflistung von Objekten, genannt heap; falls einige Variablen vom Typ Liste hat die "Object ID #29115", danach Objekt #29115 im heap wird eine Instanz-Liste oder einige geben, die davon abgeleitet werden.
Wenn MyFoo ist eine variable vom Typ Liste, eine Aussage wie " MyFoo.Add("George")' wird nicht wirklich ändern MyFoo; vielmehr bedeutet es "Überprüfen des Objekt-ID gespeichert MyFoo, und rufen Sie die "Add" - Methode des Objekts, die darin gespeichert sind. Wenn MyFoo statt "Object ID #19533", bevor die Anweisung ausgeführt wird, wird es auch weiterhin tun danach, aber Objekt ID #19533 hatten dessen Add-Methode aufgerufen wird (wahrscheinlich verändern, dass-Objekt). Umgekehrt, eine Aussage wie "MyFoo = MyBar" MyFoo halten Sie die gleiche Objekt-id als MyBar, aber nicht wirklich etwas tun, um die Objekte in Frage. Wenn MyBar statt "Object ID #59212" vor der Anweisung, dann nach der Aussage, MyFoo wird auch "ObjectId #59212". Nichts wird geschehen-Objekt ID #19533, noch Objekt ID#59212.
InformationsquelleAutor
Nur primitive Typen wie int, double etc. als Wert übergeben werden.
Komplexe Typen (wie list) übergeben werden, per Referenz (das ist eine vorübergehende Zeiger-Wert, um genau zu sein).
ref
oderout
.Also, die Stelle in meiner Antwort ist falsch?
Sie sagte: "Nur primitive Typen...die als Wert übergeben werden. Komplexe Typen...übergeben werden per Referenz." Wie gesagt, alle - Parameter werden als Wert übergeben, es sei denn, gekennzeichnet mit
ref
oderout
, nicht "nur primitive Typen.". "Komplex" ist kein gut definierter Begriff; ich nehme an, du meinst Referenz-Typen. Parameter geben Sie als Referenz-Typen werden als Wert übergeben, sofern nicht anders gekennzeichnet-mitref
oderout
.Nein, ich meinte, dass die Methode nicht das Objekt kopieren, sondern nur seine Adresse. Denke darüber nach wie in c++, in denen Sie nicht über Schlüsselwort 'ref'. Lesen Sie noch einmal sorgfältig. Ich Stimme mit Ihren Punkt über "komplexe", Zitat wäre das bessere Wort.
C# ist nicht C++. "Nein, ich meinte, dass die Methode nicht das Objekt kopieren, sondern nur seine Adresse." Abgesehen von der Schlampigkeit ("Methode nicht das Objekt kopieren"), wird der Wert kopiert, bevor Sie an die Methode übergeben. Immer, immer, immer (sofern nicht anders gekennzeichnet-mit
ref
oderout
). Für value-Typen, die Instanz ist der Wert. Für Referenz-Typen, wird der Wert der Referenz. Beachten Sie, dass dies ist nicht der gleiche wie der referent!InformationsquelleAutor