2009-06-06 7 views
1

J'ai un peu de code sur lequel j'ai travaillé pour un ami ces derniers jours. À un niveau élevé, il analyse un fichier texte et écrit dans une MDB. Pour résumer une histoire courte, j'ai un couple de boucles imbriquées en train de traiter les objets. La boucle interne n'est appelée que dans certains cas, mais lorsqu'elle le fait, elle fait des choses étranges.Valeurs de collection Changement dans la boucle

ArrayList CaseRecordItems = new ArrayList(); // this is created earlier 
string baseTif = "sometext_"; // this is created earlier 
CaseRecord cr = new CaseRecord(); (this gets populated with "stuff") 
char increment = 'A'; 

for (int i = 0; i < FirstNames.Count; i++) 
{ 
    cr.Firstname = (string)FirstNames[i]; 
    cr.Lastname = (string)LastNames[i]; 
    if (FirstNames.Count > 1) 
    { 
     cr.Tif = baseTif + increment.ToString(); 
     increment++; 
    } 
    CaseRecordItems.Add(cr); 
} 

La boucle exécute par exemple deux fois et devrait définir la valeur de cr.Tif à sometext_A et sometext_B. Cela fonctionne correctement, mais une fois que le deuxième élément est ajouté à la collection, la valeur de la première est modifiée pour le faire correspondre.

Je suppose que cela est dû à un manque de compréhension de la façon dont ces objets sont instanciés et transmis. Toute idée serait appréciée.

EDIT:

D'après les commentaires impressionnant (et mon engourdie-nutzery) le problème a été résolu. Grâce à la réponse de Dan, j'ai apporté quelques modifications au code que j'avais essayé avant d'utiliser la fonction clone (oui, la plage que j'avais essayé: P). Le nouveau bloc ressemble à ceci: ArrayList CaseRecordItems = new ArrayList(); // ceci est créé plus tôt string baseTif = "sometext_"; // ceci est créé plus tôt CaseRecord cr = new CaseRecord(); // ceci est rempli avec "stuff") char increment = 'A';

for (int i = 0; i < FirstNames.Count; i++) 
{ 
    CaseRecord cr2 = new CaseRecord(); 
    cr2 = cr.Clone();      // preserves the data from outside 
    cr2.Firstname = (string)FirstNames[i]; 
    cr2.Lastname = (string)LastNames[i]; 
    if (FirstNames.Count > 1) 
    { 
     cr2.Tif = baseTif + increment.ToString(); 
     increment++; 
    } 
    CaseRecordItems.Add(cr2); 
} 

Merci à tous pour les réponses super rapides!

+0

Pouvons-nous obtenir le code plus complet? Où cr est-il créé? –

+0

cr est un poco créé dans le bloc directement avant la boucle – kdmurray

+0

Il n'y a pas non plus de boucle foreach. –

Répondre

7

Je suppose que cr est un objet. Vous n'êtes pas en train de créer un nouveau cr à chaque fois, et ainsi vous avez deux fois la même référence dans l'arraylist, donc quand vous le modifiez la deuxième fois que vous travaillez réellement sur le même objet.

0

Comme cr ne reçoit pas de nouvelle instruction (je ne connais pas le type de cr ou je vous le montrerais), vous ajoutez simplement la même référence encore et encore. Si vous voulez ajouter de nouveaux éléments cr à CaseRecordItems, vous devez faire un nouveau cr = new TypeOfCR(); sinon, vous écrasez le même objet encore et encore.

EDIT: Assurez-vous de faire la nouvelle à l'intérieur de la boucle

0

Si vous ne créez pas cr (quoi que ce soit) à l'intérieur de la boucle, puis vous modifiez le même objet, et plus plus, chaque fois à travers la boucle. Vous voulez créer une nouvelle instance cr à l'intérieur de la boucle for.

2

Vous modifiez la valeur de l'instance cr à l'intérieur de la boucle. Chaque itération à travers la boucle utilise la même instance de cr alors quand vous le changez, ils changent tous. Pour résoudre ce problème, une méthode appropriée consiste à utiliser une instance locale dans la boucle:

for (int i = 0; i < FirstNames.Count; i++) 
{ 
    CaseRecord cr=new CaseRecord(); 

    ... 

    CaseRecordItems.Add(cr); 
} 
+0

btw ... bonne estimation sur le nom de classe. vous aviez cela ici avant que je fixe le texte de la question ... hehe. – kdmurray

1

Le problème est que la cr variable est le même à chaque fois dans la boucle, de sorte que les deux fois à travers la boucle le même objet est étant modifié et le même objet est ajouté deux fois à ArrayList.

Vous ne montrez pas assez de code pour montrer où cr est déclaré.

Avez-vous besoin de faire quelque chose comme

for (int i = 0; i < FirstNames.Count; i++) 
{ 
    CRObject cr = new CRObject(); 

    cr.Firstname = (string)FirstNames[i]; 
    cr.Lastname = (string)LastNames[i]; 
    if (FirstNames.Count > 1) 
    { 
     cr.Tif = baseTif + increment.ToString(); 
     increment++; 
    } 
    CaseRecordItems.Add(cr); 
} 
0

cr En supposant est une classe, vous devrez créer une nouvelle instance de la classe à chaque passage dans la boucle, comme cr = new crClassName(); La raison est que ce qui est ajouté à CaseRecordItems est un pointeur vers l'objet, pas une copie de celui-ci - c'est pourquoi lorsque vous le changez à la deuxième passe, la première valeur semble également changer.

1

L'objet cr a-t-il une fonction clone?

Si oui, cela devrait le faire:

CaseRecordItems.Add(cr.Clone()); 
Questions connexes