Изменение значения объектов в цикле 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;
}

Ошибка: нельзя назначить, потому что она итерационная переменная

Ответ 1

Вы не можете изменить переменную итерации цикла 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;
}

ИЗМЕНИТЬ

В комментарии вы говорите, что вам нужно изменить много полей. В этом случае было бы хорошо иметь метод UpdateStudent, который будет делать все изменения; однако я все равно сохранил бы свойства.

Если в свойствах нет дополнительной логики, кроме передачи значения, вы можете заменить их удобными автоматически реализованными свойствами.

public string Name { get; set; }

В этом случае вам придется отбросить поле name.

Ответ 2

Фактически вы не изменяете объект, о котором вы говорите, поэтому вы можете просто использовать:

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

Или еще вызовите метод:

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

В обоих случаях код не изменяет значение переменной итерации (student), поэтому все в порядке.

Но ваш исходный пример не компилируется в любом случае - переменная итерации, введенная циклом foreach, доступна только для чтения.