Werden Arrays oder Listen standardmäßig als Referenz in c # übergeben?

84

Tun sie? Oder um mein Programm zu beschleunigen, sollte ich sie als Referenz übergeben?

Jorge Branco
quelle
35
Um Ihr Programm zu beschleunigen, sollten Sie (1) sinnvolle Ziele festlegen, (2) testen, ob Sie Ihre Ziele erreicht haben, (3) wenn Sie dies nicht getan haben, ein Profilierungswerkzeug verwenden, um das Langsamste zu finden, und (4) ) das langsamste optimieren.
Eric Lippert
1
Siehe auch stackoverflow.com/q/4311226/344822
prabhakaran
3
@EricLippert Ihr Kommentar beantwortet die eigentliche Frage des OP weitaus besser als jede der veröffentlichten Antworten. Alle waren von den technischen Details "Pass Reference by Value" so abgelenkt, dass sie die eigentliche Frage nach der Leistungsoptimierung völlig übersahen. Leider hat das OP seine Bedürfnisse eher schlecht kommuniziert, und die anderen Antworten werden zumindest der Google-Masse helfen.
Dan Bechard
"Andere Antworten werden zumindest der Google-Masse helfen" - das werden sie! :)
Miki

Antworten:

208

Die Referenz wird als Wert übergeben .

Arrays in .NET sind Objekte auf dem Heap, sodass Sie eine Referenz haben. Diese Referenz wird als Wert übergeben, was bedeutet, dass Änderungen am Inhalt des Arrays vom Aufrufer gesehen werden, eine Neuzuweisung des Arrays jedoch nicht:

void Foo(int[] data) {
    data[0] = 1; // caller sees this
}
void Bar(int[] data) {
    data = new int[20]; // but not this
}

Wenn Sie den refModifikator hinzufügen , wird die Referenz als Referenz übergeben - und der Anrufer würde sehen, dass sich beide oben ändern.

Marc Gravell
quelle
28
Die Antwort ist richtig, aber ich habe einen Hass gegen Leute, die sagen, "die Referenz wird als Wert übergeben". Es verwirrt das Problem. Ja, Referenzen (Speicheradressen) werden als Wert übergeben, aber das war nicht die Frage.
WernerVA
9
@WernerVA Ich bin interessiert, wie Sie denken, Sie würden es anders ausdrücken, was korrekt und eindeutig
Marc Gravell
2
Ich würde nicht anders ausdrücken, nur vielleicht ein bisschen detaillierter.
WernerVA
Dies beantwortet nicht den Geschwindigkeitsteil der Frage. Es ist Ihnen wahrscheinlich klar, dass die Optimierung einer Referenzkopie im Vergleich zu den Hunderten anderer weitaus teurerer Operationen, die stattfinden, völlig vernachlässigbar sein wird, aber das OP hat dies ausdrücklich angefragt.
Dan Bechard
7
@Dan der Geschwindigkeitsteil ist inhärent mit dem "Wenn das Array als Wert übergeben wird - dh eine Kopie des Array-Inhalts - bedeutet dies eine Zuordnung und eine Kopie des gesamten Speichers" verknüpft. Da es sich um eine Referenz handelt, die übergeben wird, muss keine Leistungsfrage beantwortet werden. Dieser Teil der Frage wird streitig gemacht und automatisch beantwortet. Außer jetzt wird es auch hier explizit in den Kommentaren beantwortet ...
Marc Gravell
9

Sie werden als Wert übergeben (wie alle Parameter, die weder ref noch out sind), aber der Wert ist eine Referenz auf das Objekt, sodass sie effektiv als Referenz übergeben werden.

Sockel
quelle
0

Ja, sie werden standardmäßig in C # als Referenz übergeben. Alle Objekte in C # sind außer den Werttypen. Um ein bisschen genauer zu sein, werden sie "als Referenz nach Wert" übergeben; Das heißt, der Wert der Variablen, die Sie in Ihren Methoden sehen, verweist auf das ursprünglich übergebene Objekt. Dies ist ein kleiner semantischer Punkt, der jedoch manchmal wichtig sein kann.

Paul Sonier
quelle
9
Die Referenz wird als Wert übergeben. was sich sehr von "sie werden als Referenz übergeben" unterscheidet.
Marc Gravell
1
Dies ist das genaue Gegenteil der Wahrheit. Zitat aus diesem Beitrag von John Skeet : "Standardmäßig werden alle Parameter in C # als Wert übergeben. Parameter werden nur als Referenz übergeben, wenn Sie explizit einen Out- oder Ref-Modifikator einschließen. Sie müssen jedoch wissen, wann der Typ des Parameters ist ist ein Referenztyp, Sie übergeben eher eine Referenz als ein tatsächliches Objekt ". Es wird nur die Referenz (die Speicheradresse) als Wert übergeben.
Alexlomba87