Ich habe ein Objekt, das sich im Speicherstatus des Programms befindet, und einige andere Worker-Funktionen, an die ich das Objekt übergebe, um den Status zu ändern. Ich habe es per Ref an die Arbeiterfunktionen weitergegeben. Ich bin jedoch auf die folgende Funktion gestoßen.
byte[] received_s = new byte[2048];
IPEndPoint tmpIpEndPoint = new IPEndPoint(IPAddress.Any, UdpPort_msg);
EndPoint remoteEP = (tmpIpEndPoint);
int sz = soUdp_msg.ReceiveFrom(received_s, ref remoteEP);
Es verwirrt mich, weil beide received_s
und remoteEP
Sachen von der Funktion zurückgeben. Warum braucht remoteEP
man ein ref
und received_s
nicht?
Ich bin auch ein AC-Programmierer, daher habe ich ein Problem damit, Zeiger aus meinem Kopf zu bekommen.
Bearbeiten: Es sieht so aus, als wären Objekte in C # Zeiger auf das Objekt unter der Haube. Wenn Sie also ein Objekt an eine Funktion übergeben, können Sie den Objektinhalt über den Zeiger ändern. Das einzige, was an die Funktion übergeben wird, ist der Zeiger auf das Objekt, damit das Objekt selbst nicht kopiert wird. Sie verwenden ref oder out, wenn Sie in der Funktion, die einem Doppelzeiger ähnelt, ausschalten oder ein neues Objekt erstellen möchten.
if (int.TryParse(text, out int value)) { ... use value here ... }
Stellen Sie sich einen Nicht-Ref-Parameter als Zeiger und einen Ref-Parameter als Doppelzeiger vor. Das hat mir am meisten geholfen.
Sie sollten Werte fast nie mit ref übergeben. Ich vermute, dass das .Net-Team es ohne Interop-Bedenken niemals in die ursprüngliche Spezifikation aufgenommen hätte. Die OO-Methode, um mit den meisten Problemen umzugehen, die ref-Parameter lösen, ist:
Für mehrere Rückgabewerte
Für Grundelemente, die sich in einer Methode infolge des Methodenaufrufs ändern (Methode hat Nebenwirkungen auf Grundelemente)
quelle
IPAddress.TryParse(string, out IPAddress)
.if (int.TryParse("123", out var theInt) { /* use theInt */ }
wir es getan hätten.var candidate = int.TrialParse("123"); if (candidate.Parsed) { /* do something with candidate.Value */ }
Es ist mehr Code, aber es stimmt viel besser mit dem Design der C # -Sprache überein.Sie könnten wahrscheinlich eine ganze C # -App schreiben und niemals Objekte / Strukturen per Referenz übergeben.
Ich hatte einen Professor, der mir folgendes sagte:
Ich stimme seinem Rat zu und in meinen mehr als fünf Jahren seit der Schule hatte ich nie einen Bedarf dafür, außer das Framework oder die Windows-API aufzurufen.
quelle
SetName(person, "John Doe")
, ändert sich die Namenseigenschaft und diese Änderung wird für den Anrufer übernommen.Da receive_s ein Array ist, übergeben Sie einen Zeiger auf dieses Array. Die Funktion manipuliert die vorhandenen Daten, ohne die zugrunde liegende Position oder den zugrunde liegenden Zeiger zu ändern. Das Schlüsselwort ref gibt an, dass Sie den tatsächlichen Zeiger an die Position übergeben und diesen Zeiger in der Außenfunktion aktualisieren, sodass sich der Wert in der Außenfunktion ändert.
Beispielsweise ist das Bytearray ein Zeiger auf denselben Speicher, bevor und nachdem der Speicher gerade aktualisiert wurde.
Die Endpunktreferenz aktualisiert tatsächlich den Zeiger auf den Endpunkt in der externen Funktion auf eine neue Instanz, die innerhalb der Funktion generiert wird.
quelle
Stellen Sie sich einen Verweis so vor, als würden Sie einen Zeiger als Referenz übergeben. Wenn Sie keine Referenz verwenden, übergeben Sie einen Zeiger als Wert.
Besser noch, ignorieren Sie, was ich gerade gesagt habe (es ist wahrscheinlich irreführend, insbesondere bei Werttypen) und lesen Sie diese MSDN-Seite .
quelle
Mein Verständnis ist, dass alle von der Object-Klasse abgeleiteten Objekte als Zeiger übergeben werden, während gewöhnliche Typen (int, struct) nicht als Zeiger übergeben werden und ref erfordern. Ich bin mir bei der Zeichenfolge nicht sicher (wird sie letztendlich von der Objektklasse abgeleitet?)
quelle
Obwohl ich der allgemeinen Antwort von Jon Skeet und einigen anderen Antworten zustimme, gibt es einen Anwendungsfall für die Verwendung
ref
, und zwar zur Verschärfung der Leistungsoptimierungen. Bei der Leistungsprofilerstellung wurde beobachtet, dass das Festlegen des Rückgabewerts einer Methode geringfügige Auswirkungen auf die Leistung hat, wohingegen die Verwendungref
als Argument, bei dem der Rückgabewert in diesen Parameter eingefügt wird, dazu führt, dass dieser geringfügige Engpass beseitigt wird.Dies ist wirklich nur dann nützlich, wenn Optimierungsbemühungen auf ein extremes Niveau gebracht werden, wodurch die Lesbarkeit und möglicherweise die Testbarkeit und Wartbarkeit beeinträchtigt werden, um Millisekunden oder möglicherweise Split-Millisekunden zu sparen.
quelle
Grundnullregel zuerst: Primitive werden im Kontext der beteiligten TYPEN als Wert (Stapel) und Nicht-Primitiv als Referenz (Heap) übergeben.
Die beteiligten Parameter werden standardmäßig als Wert übergeben. Guter Beitrag, der die Dinge im Detail erklärt. http://yoda.arachsys.com/csharp/parameters.html
Wir können (mit Warnung) sagen, dass nicht-primitive Typen nichts als Zeiger sind. Und wenn wir sie als Referenz übergeben, können wir sagen, dass wir Doppelzeiger übergeben
quelle