2017-05-10 3 views
0

Ich versuche, den Wert in der inneren Liste durch Iterieren der Liste zu ändern. Allerdings bekomme ich das gleiche Ergebnis für die innere Liste unabhängig von der äußeren Liste. Ich erwarte das Ergebnis der maxSpeed ist für verschiedene Fahrzeuge unterschiedlich.Ändern der Liste in der Liste in C#

Hoffe jemand könnte dabei helfen.

Beachten Sie, dass dies kein Zufallsgeneratorproblem ist. Dies ist nur ein Beispielcode, den ich produziere, und dieses Problem existiert in meinem Projektcode ohne die Verwendung von Zufallszahlengenerator.

Run C# code here

List<Vehicle> mainList = new List<Vehicle>(); 
List<Properties> defaultPropertyList = new List<Properties>{ 
    new Properties() { maxSpeed = 0, isTwoDoor = true }, 
    new Properties() { maxSpeed = 0, isTwoDoor = true }, 
}; 


mainList.Add(
    new Vehicle() { 
     number = 1, 
     property = new List<Properties>(defaultPropertyList) 
    } 
); 
mainList.Add(
    new Vehicle() { 
     number = 2, 
     property = new List<Properties>(defaultPropertyList) 
    } 
);   

foreach(Vehicle vehicle in mainList) { 
    Random rnd = new Random(); 
    vehicle.property.ForEach(x => x.maxSpeed = rnd.Next(1, 100)); 
} 
+0

Versuchen Sie, den Zufallszahlengenerator auf Saatgut – Gururaj

+0

um bessere Ergebnisse zu erhalten, wenn Sie 'Properties' eine Klasse ist, dann wird es als Referenz übergeben werden. Auf diese Weise erhalten beide Fahrzeugobjekte eine eindeutige Liste. Jede eindeutige Liste enthält jedoch Verweise auf die ** gleichen ** 'Properties'-Objekte. Kopieren Sie Ihre Objekte oder verwenden Sie Werttypen (wie eine Struktur). – Adwaenyth

+0

@Gururaj Ich glaube nicht, dass es ein Problem des Zufallszahlengenerators ist, basierend auf dem Ergebnis. – vincentsty

Antwort

5

Das Problem ist, dass, wenn Sie das property Feld für jedes Fahrzeug zu initialisieren, Sie Verweise auf die gleichen zwei Properties Objekte hinzufügen (oben definiert). Sie existieren also in allen Fahrzeugen, und wenn Sie eine ändern, wird sie an beiden Stellen modifiziert (da es dieselbe Referenz ist).

Sie möchten stattdessen Kopien der Objekte in der defaultPropertyList erstellen, wenn Sie ein neues Fahrzeug initialisieren. Dann werden sie unabhängig existieren.

Ein Ansatz: Erstellen Sie einen neuen Konstruktor für Vehicle, der die Standardeigenschaften übernimmt und sie dort kopiert.

public Vehicle(List<Properties> defaultProps) 
{ 
    property = new List<Properties>(); 
    foreach (var p in defaultProps) 
    { 
    var newProp = new Properties { 
            maxSpeed = p.maxSpeed, 
            isTwoDoor = p.isTwoDoor 
            // add any other properties here 
           }; 
    property.Add(newProp); 
    } 
} 
+0

Ein bisschen verwirrend für mich ... können Sie einen Beispielcode der Implementierung bereitstellen.Ich habe Methode müssen einen Rückgabetyp mit Ihrem Code-Snipper haben – vincentsty

+0

@vincentsty Ich fügte einige weitere Details zu dem Snippet –

+0

Ich habe eine Fehlermeldung, dass die Methode nicht definiert ist. http://rextester.com/IUR51211 – vincentsty

1

defaultPropertyList ist nur eine Liste mit einem Satz von Elementen. Jeder Vehicle hat dieselbe Instanz von List<Properties>. Es gibt keine pro Vehicle. Es gibt nur einen, und sie teilen ihn alle. Das ist der Grund, egal wie Sie die Eigenschaften ändern, sie alle haben die gleichen Eigenschaften.

Um es zu beheben, erstellen Sie keine und teilen Sie es. Erstelle einfach so viele, wie du brauchst. Vielleicht bist du es nicht, aber als ich angefangen habe, hatte ich Angst, viele Objekte zu erschaffen und dachte, ich könnte optimieren, indem ich so wenig wie möglich erschaffe.

Während es stimmt, dass wir unnötigerweise nicht viele teure Objekte erstellen möchten, müssen wir nicht geizig sein. Erstellen Sie so viele, wie Sie benötigen. Zum Beispiel ist es in einer Webanwendung unmöglich, sogar zu verfolgen, wie viele Objekte erzeugt werden, nur um auf eine einzelne Anfrage zu antworten.

Sie können dies nur tun:

Random rnd = new Random(); // Despite what I just said, 
          // you only need one of these this time. 
foreach(Vehicle vehicle in mainList) {   
    vehicle.property = new List<Properties>{ 
     new Properties() { maxSpeed = rnd.Next(1, 100), isTwoDoor = true }, 
     new Properties() { maxSpeed = rnd.Next(1, 100), isTwoDoor = true }, 
} 
+0

Wie könnte ich es ändern, um es mehrere Instanzen zu haben? – vincentsty

+0

Es wäre einfacher, wenn 'vehicle.property.ForEach()' in diesem Fall beibehalten werden könnte. Nur der maxSpeed ​​muss geändert werden (und beachten Sie, dass es viele Eigenschaften gibt, um im selben Fall den gleichen Wert zu behalten) und es scheint mir, dass es überflüssig ist, jede Eigenschaft erneut auf diese Weise neu zu deklarieren. – vincentsty