web-dev-qa-db-fra.com

Changer la valeur des objets dans la boucle foreach?

À un endroit, j'utilise la liste de chaînes dans ce cas, je peux changer la valeur de la chaîne comme code donné ci-dessous,

foreach(string item in itemlist.ToList())
{
    item=someValue; //I am able to do this 
}

Mais pour un objet de classe, je ne suis pas en mesure de modifier la valeur des membres de l'objet, le code est comme ci-dessous,

public class StudentDTO
{
    string name;
    int rollNo;
}

studentDTOList=GetDataFromDatabase();

foreach(StudentDTO student in studentDTOList.ToList())
{
      studentDTO=ChangeName(studentDTO); //Not working 
}

private StudentDTO ChangeName(StudentDTO studentDTO)
{
     studentDTO.name=SomeName;
     return studentDTO;
}

L'erreur est: impossible à attribuer car il s'agit d'une variable d'itération

19
user2553512

Vous ne pouvez pas modifier la variable d'itération d'une boucle foreach, mais vous pouvez modifier les membres de la variable d'itération. Par conséquent, changez la méthode ChangeName en

private void ChangeName(StudentDTO studentDTO)
{
    studentDTO.name = SomeName;
}

Notez que studentDTO est un type de référence. Il n'est donc pas nécessaire de renvoyer l'élève changé. Ce que la méthode ChangeName obtient, ce n'est pas une copie de l'étudiant mais une référence à l'objet étudiant unique. La variable d'itération et le studentDTOList font tous deux référence au même objet étudiant que le paramètre studentDTO de la méthode.

Et changez la boucle en

foreach(StudentDTO student in studentDTOList)
{
    ChangeName(student);
}

Cependant, des méthodes comme ChangeName sont inhabituelles. La voie à suivre consiste à encapsuler le champ dans une propriété

private string name;
public string Name
{
    get { return name; }
    set { name = value; }
}

Vous pouvez ensuite changer la boucle en

foreach(StudentDTO student in studentDTOList)
{
    student.Name = SomeName;
}

MODIFIER

Dans un commentaire, vous dites que vous devez changer de nombreux champs. Dans ce cas, il serait correct d'avoir une méthode UpdateStudent qui ferait toutes les modifications; mais je garderais quand même les propriétés.

S'il n'y a pas de logique supplémentaire dans les propriétés en plus de passer par une valeur, vous pouvez les remplacer par les propriétés pratiques implémentées automatiquement.

public string Name { get; set; }

Dans ce cas, vous devrez supprimer le champ name.

27

De toute façon, vous ne modifiez pas l'objet auquel vous faites référence, vous pouvez donc simplement utiliser:

foreach (StudentDTO student in studentDTOList)
{
    student.name = SomeName;
}

Ou encore appelez une méthode:

foreach (StudentDTO student in studentDTOList)
{
    ChangeStudent(student);
}

Dans les deux cas, le code ne change pas la valeur de la variable d'itération (student) donc c'est correct.

Mais votre exemple d'origine ne se compile pas de toute façon - une variable d'itération introduite par une boucle foreach est en lecture seule.

20
Jon Skeet