25. september 2007 - 00:01Der er
9 kommentarer og 1 løsning
List - hvad er forsellen på for / foreach?
Jeg har følgende kode hvor LOfMyInt32 er en static collection af List. Den første for-løkke fungerer i det at den får ændret indholdet i Listen. De to andre (som er udkommenteret) compiler og kører OK, men ændringerne som InternalUpdate1() skulle udføre på objektet bliver på en eller anden måde ikke gemt i objektet. InternalUpdate1 overføre bare værdien af en private int til en anden private int.
for (int i = 0; i < LOfMyInt32.Count; i++) { MyInt32 temp = LOfMyInt32[i]; temp.InternalUpdate1(); LOfMyInt32[i] = temp; } //for (int i = 0; i < LOfMyInt32.Count; i++) //{ // LOfMyInt32[i].InternalUpdate1(); //}
//foreach (MyInt32 i in LOfMyInt32) //{ // i.InternalUpdate1(); //}
Hvorfor fungere 2 + 3 ikke som løsning nummer 1? og er der en mere elegant måde (speed is essential!!!) hvorved jeg kan gøre det samme? Det skal måske lige nævens at jeg har prøvet mig frem med List.ForEach() - men uden held :(
Hvordan kan det være? Men det vil sige at de to nedenstående for løkker ville virke hvis MyInt32 var af typen class? Der er ikke en hurtigere metode end den jeg benytter?
Ja, de ville fungere hvis du ændre struct til class i din definition.
Hvorfor?
Problemstillingen er faktisk den samme som, hvis du kalder en metode med hhv. en struct eller en class – i det første tilfælde overføres argumenterne som kopier, i det andet tilfælde som referencer.
Eksempel 1 - class-typer bliver reference overført:
class Program { static void Main(string[] args) { MyClassType myClass = new MyClassType(7-9-13); DoSomething(myClass); Console.WriteLine(myClass.tal); }
static void DoSomething(MyClassType argument) { // Her arbejder vi direkte med selve myClass objektet argument.tal = 42; } }
class MyClassType { public int tal; public MyClassType(int tal) { this.tal = tal; } }
Eksempel 2 - stuct-typer bliver kopi overført:
class Program { static void Main(string[] args) { MyStructType myStruct = new MyStructType(7-9-13); DoSomething(myStruct); Console.WriteLine(myStruct.tal); }
static void DoSomething(MyStructType argument) { // Her arbejder vi med en kopi af selve myStruct objektet argument.tal = 42; } }
struct MyStructType { public int tal; public MyStructType(int tal) { this.tal = tal; } }
Det er præcis den samme mekanisme som er på spil i dine løkker.
Struct-tilfældet: De to sidste løkker laver en (temporær) kopi af listens elementer, og det er på kopierne at du kalder din InternalUpdate1() – ikke på selve liste elementet. Da kopierne prompte smides væk ser det ikke ud som om at der sker noget som helst, og da i hvert fald slet ikke med listens elementer.
Class-tilfældet: De to sidste lister laver en reference til listens elementer. Når du kalder din InternalUpdate1() vil den derfor ske direkte mod elementet i listen, og den vil derfor slå igennem.
Begge tilfælde: I din første løkke oprettes der også en kopi (temp) og det er på denne at InternalUpdate1() kaldes. Men i stedet for at smide den væk, indsætter du nu den opdaterede kopi i stedet for den gamle i listen.
Nu spørger jeg måske lidt hovedløst; men hvis jeg lavede min liste om til et array - ville jeg så opleve det samme? nielle: ud fra din forklaring ville jeg jo selv svare at det ville jeg...
godt så - nu tror jeg at jeg er ved at fange det. Nielle, jeg tror denne her går til dig, så hvis du lige kaster et svar ind så skal jeg tildele dig nogle point...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.