Sie sind begrenzter. Sie können ++ für einen Zeiger sagen, aber nicht für ref
oder out
.
BEARBEITEN Einige Verwirrung in den Kommentaren, um absolut klar zu sein: Der Punkt hier ist, mit den Fähigkeiten von Zeigern zu vergleichen. Sie können dieselbe Operation nicht als ptr++
für eine ref
/ out
ausführen, d. H. Sie adressieren eine benachbarte Position im Speicher. Es ist wahr (aber irrelevant hier), dass Sie das Äquivalent von (*ptr)++
ausführen können, aber das wäre, es mit den Fähigkeiten von -Werten zu vergleichen, nicht mit Zeigern.
Es ist eine sichere Wette, dass sie intern nur Zeiger sind, weil der Stapel nicht verschoben wird und C # sorgfältig organisiert ist, so dass sich ref
und out
immer auf eine aktive Region des Stapels beziehen.
BEARBEITEN Um noch einmal ganz klar zu sein (wenn es nicht bereits aus dem folgenden Beispiel klar war), ist der Punkt hier nicht, dass ref
/ out
nur Zeigen Sie auf den Stapel. Es ist das wenn es auf den Stack zeigt, wird durch die Sprachregeln garantiert, dass es nicht zu einem ungeordneten Pointer wird. Diese Garantie ist notwendig (und relevant / interessant hier), weil der Stapel Informationen einfach in Übereinstimmung mit Methodenaufruf-Exits verwirft, ohne dass überprüft wird, ob noch Verweiser vorhanden sind.
Umgekehrt, wenn ref
/ out
sich auf Objekte im GC-Heap bezieht, ist es nicht verwunderlich, dass diese Objekte so lange am Leben erhalten werden können, wie es nötig ist: Der GC-Heap ist genau dafür entworfen, Objekte für irgendeinen zu behalten Länge der Zeit, die von ihren Referrern benötigt wird, und bietet Pinning (siehe Beispiel unten), um Situationen zu unterstützen, in denen das Objekt nicht durch GC-Komprimierung verschoben werden darf.
Wenn Sie jemals mit Interop in unsicherem Code spielen, werden Sie feststellen, dass ref
sehr eng mit Zeigern verwandt ist. Wenn eine COM-Schnittstelle beispielsweise wie folgt deklariert wird:
Die Interop-Assembly wird daraus folgendes machen:
%Vor%Und Sie können dies tun, um es aufzurufen (ich glaube, das COM-Interop-Zeug kümmert sich darum, das Array zu fixieren):
%Vor% Mit anderen Worten: ref
auf das erste Byte gibt Ihnen Zugriff auf alles; es ist anscheinend ein Zeiger auf das erste Byte.
Referenzparameter in C # können verwendet werden, um eine Verwendung von Zeigern zu ersetzen, ja. Aber nicht alle.
Eine weitere häufige Verwendung von Zeigern besteht in der Möglichkeit, über ein Array zu iterieren. Out / ref-Parameter können das nicht, also nein, sie sind nicht "die gleichen wie Zeiger".
ref
und out
werden nur zusammen mit Funktionsargumenten verwendet, um anzugeben, dass das Argument als Referenz anstelle von Wert übergeben werden soll. In diesem Sinne, ja, sie sind etwas wie Zeiger in C ++ (eher wie Referenzen tatsächlich). Lesen Sie mehr dazu in diesem Artikel .
Eigentlich würde ich sie mit C ++ - Verweisen und nicht mit Zeigern vergleichen. Pointers, in C ++ und C, sind ein allgemeineres Konzept und Referenzen werden tun, was Sie wollen.
All dies sind natürlich zweifellos Hinweise unter den Deckblättern.
Während Vergleiche im Auge des Betrachters sind ... sage ich nein. 'ref' ändert die Aufrufkonvention , nicht jedoch den Typ der Parameter. In Ihrem C ++ - Beispiel haben d1 und d2 den Typ int *. In C # sind sie immer noch Int32, sie werden einfach als Referenz und nicht als Wert übergeben.
Übrigens tauscht Ihr C ++ - Code seine Eingaben im herkömmlichen Sinne nicht wirklich aus. Verallgemeinern Sie es so:
%Vor%... funktioniert nur, wenn alle Typen T Kopierkonstruktoren haben und selbst dann viel ineffizienter sind als das Vertauschen von Zeigern.
Die kurze Antwort ist Ja (ähnliche Funktionalität, aber nicht genau der gleiche Mechanismus).
Wenn Sie FxCop verwenden, um Ihren Code zu analysieren, führt die Verwendung von out
und ref
zu einem "Microsoft.Design" -Fehler von "CA1045: DoNotPassTypesByReference".