Warum werden Objekte automatisch als Referenz übergeben?

8

Ich habe eine allgemeine Frage zur Tief- und Flachkopie im Zusammenhang mit dem Pass-by-Reference- und Pass-by-Value-Konzept von C #:

In C # müssen explizit Methoden erstellt werden, die Zeiger / Referenzen akzeptieren, um diese an die Methode übergeben zu können. Allerdings verhalten sich zumindest Objekte, die als Parameter an Methoden / Konstruktoren übergeben werden, anders als die übrigen. Es scheint, dass sie immer als Referenz weitergegeben werden, wenn kein zusätzliches Klonen wie hier beschrieben durchgeführt wird: Ссылка .

Warum werden Objekte automatisch als Referenz übergeben? Gibt es einen besonderen Vorteil darin, den Klonprozess für sie zu erzwingen, anstatt Objekte in diesen Fällen mehr wie int, double, boolean usw. zu behandeln?

Hier ist ein Codebeispiel, das veranschaulicht, was ich meine:

%Vor%

Dies führt zu:

%Vor%

Instanzen von MyCol werden immer als Referenz übergeben, während die anderen Argumente als Wert übergeben werden. Ich müsste ICloneable in den Klassen MyColor und A implementieren. Auf der anderen Seite ist die'ref'-Anweisung in C # vorhanden, die verwendet werden sollte, um explizit zuzulassen und eine Weitergabe als Referenz durchzuführen.

Vorschläge sind willkommen!

    
Florian R. Klein 13.04.2014, 09:56
quelle

5 Antworten

31
  

Warum werden Objekte automatisch als Referenz übergeben?

Sie sind nicht.

  

Gibt es einen besonderen Vorteil darin, den Klonprozess für sie zu erzwingen, anstatt Objekte in diesen Fällen mehr wie int, double, boolean usw. zu behandeln?

Es gibt keinen "Klonprozess" für Referenztypen, nur für Werttypen.

Ich denke, du verwirrst verschiedene Konzepte:

  • Werttypen vs. Referenztypen

    Für Werttypen (z. B. primitive numerische Typen, Aufzählungszeichen und Strukturen wie DateTime ) ist der Wert der Variablen das Objekt selbst. Wenn Sie die Variable einer anderen zuweisen (oder als Wert übergeben), wird eine Kopie des Objekts erstellt.

    Bei Referenztypen (z. B. object , string , Klassen (nicht Strukturen) usw.) ist der Wert der Variablen eine Referenz auf das Objekt. Wenn Sie die Variable einer anderen zuweisen (oder sie als Wert übergeben), wird eine Kopie der Referenz erstellt, sodass sie immer noch auf dieselbe Objektinstanz verweist.

  • Übergabe der Parameter nach Wert vs durch Referenz

    Das Übergeben von Parametern als Wert bedeutet, dass Sie eine Kopie des Werts übergeben. Je nachdem, ob es sich um einen Werttyp oder um Referenztypen handelt, bedeutet dies eine Kopie des Objekts selbst oder eine Kopie der Referenz. Wenn der Angerufene Mitglieder eines als Parameter übergebenen Wertetyps ändert, sieht der Aufrufer die Änderungen nicht, da der Angerufene an einer Kopie arbeitet. Auf der anderen Seite, wenn der Aufrufer Mitglieder eines als Parameter übergebenen Referenztyps ändert, sieht der Aufrufer die Änderungen, weil der Aufgerufene und der Aufrufer beide einen Verweis auf dieselbe Objektinstanz haben.

    Das Übergeben von Parametern als Referenz bedeutet, dass Sie eine Referenz an eine Variable übergeben (die eine Variable vom Werttyp oder Referenztyp sein kann). Der Wert wird nicht kopiert: Er wird zwischen dem Anrufer und dem Angerufenen geteilt. Jede vom Angerufenen vorgenommene Änderung (einschließlich der Zuweisung eines neuen Werts an den Parameter) wird vom Aufrufer erkannt.

    Sofern nicht anders angegeben (mit den Schlüsselwörtern ref oder out ), werden alle Parameter als Wert übergeben, einschließlich Referenztypen. Bei Referenztypen ist der Wert, der übergeben wird, eine Referenz, wird aber immer noch als Wert übergeben.

Ich schlage vor, dass Sie Jon Skeets Artikel Parameter in C # zur besseren Erklärung lesen.

>     
Thomas Levesque 13.04.2014, 10:11
quelle
2

Alle Methodenargumente werden als Wert übergeben, es sei denn, Sie geben explizit an, dass sie per Referenz mit dem Schlüsselwort ref oder out übergeben werden sollen. Das heißt, wenn Sie eine Variable an einen Methodenparameter übergeben, wird der Inhalt der Variablen kopiert und an die Methode übergeben.

Wenn die Variable ein Werttyp ist, was im Grunde ein struct bedeutet, dann enthält die Variable ein Objekt und das Objekt wird kopiert. Wenn die Variable ein Referenztyp ist, was im Grunde eine class bedeutet, enthält die Variable einen Verweis auf ein Objekt, so dass die Referenz kopiert wird.

Wenn Sie einen Parameter als ref oder out deklarieren, wird ein Verweis auf die Variable erstellt, der an die Methode übergeben wird. Wenn die Variable ein Objekt enthält, wird eine Referenz auf dieses Objekt erstellt, und wenn die Variable eine Referenz enthält, wird eine Referenz auf diese Referenz erstellt.

    
jmcilhinney 13.04.2014 10:12
quelle
2

Ich formuliere deine Frage: Warum brauchen wir Unterricht? Können wir nicht nur Strukturen haben?

Nicht alle Objekte können sicher kopiert werden. Sie können eine FileStream oder eine Button beispielsweise nicht logisch kopieren. Diese Objekte haben eine Identität und Sie möchten, dass sich der gesamte Code auf das einzige Objekt bezieht.

    
usr 13.04.2014 10:17
quelle
0

Eine Variable, ein Parameter oder ein Feld eines Klassen- oder Schnittstellentyps (zusammen "Referenztypen") enthält kein Klassenobjekt; es enthält ein Objekt Bezeichner . Ebenso enthält ein Array eines Referenztyps keine Objekte. Es enthält Objektbezeichner.

Auch wenn Objekten in .NET keine lesbare Kennung zugeordnet ist, kann es hilfreich sein, sie so zu betrachten, als ob sie dies tun würden: wenn mindestens eine Anzahl (z. B. 592) von Objekten während des Kurses erstellt wird Bei der Ausführung eines Programms wird genau das eine Objekt das 592ste sein; Sobald das 592. Objekt erstellt ist, wird kein anderes Objekt jemals 592. sein. Es gibt keine Möglichkeit, herauszufinden, welches Objekt das 592. ist, aber wenn eine Variable, die einen Verweis auf das 592. Objekt enthält, als Nicht-Ref-Parameter an eine Methode übergeben wird, wird sie weiterhin einen Verweis auf das 592. Objekt bei der Methode halten kehrt zurück. Wenn Objekt # 592 eine Referenz auf eine Instanz von Car ist, die rot gefärbt ist, enthält eine lokale Variable myCar "Objekt-ID # 592", und eine ruft eine Methode PaintCar(myCar); auf, dann erhält diese Methode Object #592" . Wenn diese Methode das Auto blau malt, wird myCar bei der Rückkehr "Objekt # 592" halten, wodurch ein blaues Auto identifiziert wird.

    
supercat 17.04.2014 15:29
quelle
-2

ok schlecht bearbeite das: ich stehe vom unten stehenden Artikel korrigiert

humm Ich denke, ich bin nicht gut darin Dinge zu erklären.

    
will_m 13.04.2014 10:11
quelle