Frage

Ich habe ein C# -Programm von mir debuggen und nach mehreren fruchtlosen Zeitspannen entdeckte, dass der Fehler von "versehentlich" durch die Übergabe eines Arrays durch Bezugnahme statt nach Wert stammt.

Hier ist ein Pseudocode:

//1st pass
currentVertices = levels[0].vertices;   
currentVertices[0].Position.Z -= 10;

//2nd pass
currentVertices = levels[1].vertices;
currentVertices[0].Position.Z -= 10;

//3rd pass
currentVertices = levels[0].vertices;
currentVertices[0].Position.Z -= 10;  

//currentVertices[0].Position.Z is now 10 less than expected;
//20 less than it started. Further loops will increase the difference in expected
//value.

Ich hatte nicht damit gerechnet, das Array durch Bezug genommen zu haben, aber ich habe es trotzdem versehentlich getan.

Gibt es eine Möglichkeit, ein Array von zuzuweisen Wert statt nach Bezugnahme? Ich weiß, dass ich durch beide Arrays iterieren kann und jeden Begriff einzeln zuweisen kann, aber das scheint unnötig komplex zu sein. Ich bin mir einigermaßen sicher, dass die Clone () -Funktion, Klone, die Werte ohne die jeweiligen Referenzen, aber die einzige Möglichkeit, nach Wert zuzuweisen? Dh currentVertices = levels[1].vertices.Clone();

Ist Clone () nicht allgemein entmutigt? Was ist die beste Praxis, um Arrays nach Wert zu übergeben?

Kurzfristig habe ich einfach festgesagt, was die Werte nach dem Laden sein sollten.

Wie einer meiner Moderatorfreunde bemerkte,

"Ich sehe, dass Sie Pass-by-Referenz durch BY-Pass-Reference gelöst haben."

War es hilfreich?

Lösung

Nun, in C# werden nur Werttypen "nach Wert" übergeben. (Dies ist eine zu vereinfachte Vereinfachung, aber das ist eine anständige Art, sie anzusehen.) Alles andere ist tatsächlich eine Referenz, die mit einem Wert übergeben wird, der dem Bestehen eines Zeigers ähnlich ist. (Beachten Sie, dass dies von der Übergabe von "By Ref" unterschiedlich ist, was das Update einer Variablen in einer Anrufmethode ermöglichen würde.)

Sie haben zwei Optionen:

  1. Refactor Ihren Code, um zu vermeiden, die Objekte im Array zu mutieren
  2. Tiefklone das Array

Diese sind ungefähr in der Reihenfolge, die ich empfehlen würde.

Andere Tipps

Gibt es eine Möglichkeit, ein Array nach Wert anstelle von Referenz zuzuweisen?

Nr. Variablen der Referenztypen (und des Systems.Array ist ein Referenztyp) Referenz ihrer Instanzen.


Es scheint mir, dass Sie erwarten, dass die Eckices -Eigenschaft Ihnen eine tiefe Kopie des Arrays anstelle des Originals gibt.

Auch wenn Sie anrufen Klon, das ist eine flache Kopie. Klon macht keine Kopien des Inhalts des Arrays.

Wenn Sie eine tiefe Kopie haben müssen, empfehle ich eine Serialisierung. Das kann für diese spezielle Anwendung übertrieben sein.

Wenn Sie wirklich ein neues Array an die Funktion übergeben müssen, .Clone() ist der schnellste Weg, es zu tun. In dieser Situation würde ich jedoch normalerweise in Betracht ziehen, zu verwenden Array.AsReadOnly Stattdessen geben Sie eine Collection Wrapper um dein Array.

Wie Msdn in Bezug auf AsReadOnly:

Um Änderungen am Array zu verhindern, legen Sie das Array nur durch diesen Wrapper frei.

Eine Sammlung, die nur schreibgeschützt ist, ist einfach eine Sammlung mit einer Wrapper, die verhindert, dass die Sammlung geändert wird. Wenn Änderungen an der zugrunde liegenden Sammlung vorgenommen werden, spiegelt die schreibgeschützte Sammlung diese Änderungen wider.

Diese Methode ist eine O (1) -Operation.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top