web-dev-qa-db-ja.com

foreachループでオブジェクトの値を変更しますか?

ある場所では、文字列のリストを使用しています。その場合、以下のコードとして文字列の値を変更できます。

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

しかし、クラスのオブジェクトの場合、オブジェクトのメンバー値を変更することはできません。コードは次のとおりです。

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;
}

エラーは次のとおりです:反復変数であるため割り当てることができません

19
user2553512

Foreachループの反復変数は変更できませんが、反復変数のメンバーは変更できます。したがって、ChangeNameメソッドを

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

studentDTOは参照型であることに注意してください。したがって、変更された学生を返却する必要はありません。 ChangeNameメソッドが取得するものは、生徒のコピーではなく、一意の生徒オブジェクトへの参照です。反復変数とstudentDTOListは両方とも、メソッドのstudentDTOパラメーターと同じ学生オブジェクトを参照します。

そして、ループを

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

ただし、ChangeNameなどのメソッドは珍しいです。方法は、フィールドをプロパティにカプセル化することです

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

その後、ループを

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

[〜#〜] edit [〜#〜]

コメントでは、多くのフィールドを変更する必要があると言います。その場合、すべての変更を行うメソッドUpdateStudentを使用してもかまいません。ただし、引き続きプロパティを保持します。

プロパティに値を渡す以外に追加のロジックがない場合は、便利な自動実装プロパティに置き換えることができます。

public string Name { get; set; }

その場合、フィールドnameをドロップする必要があります。

とにかく参照しているオブジェクトを実際に変更するわけではないので、次のように使用できます。

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

または、まだメソッドを呼び出します:

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

どちらの場合も、コードは反復変数(student)の値を変更しないため、問題ありません。

しかし、元の例はとにかくコンパイルされません-foreachループによって導入された反復変数は読み取り専用です。

20
Jon Skeet