C# 在 foreach 循环中更改对象值?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17676974/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 10:10:25  来源:igfitidea点击:

Changing objects value in foreach loop?

c#loopsforeachenumeration

提问by

In one place i am using the list of string in that case the i am able to change the value of the string as code given below,

在一个地方,我正在使用字符串列表,在这种情况下,我可以将字符串的值更改为下面给出的代码,

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

But for object of class i am not able to alter the members value of the object the code is as below,

但是对于类的对象,我无法更改对象的成员值,代码如下,

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

Error is : Can not assign because it's iteration variable

错误是:无法分配,因为它是迭代变量

采纳答案by Olivier Jacot-Descombes

You cannot change the iteration variable of a foreach-loop, but you can change members of the iteration variable. Therefore change the ChangeNamemethod to

您不能更改 foreach 循环的迭代变量,但可以更改迭代变量的成员。因此将ChangeName方法更改为

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

Note that studentDTOis a reference type. Therefore there is no need to return the changed student. What the ChangeNamemethod gets, is not a copy of the student but a reference to the unique student object. The iteration variable and the studentDTOListboth reference the same student object as does the studentDTOparameter of the method.

请注意,这studentDTO是一个引用类型。因此,无需返回已更改的学生。该ChangeName方法得到的不是学生的副本,而是对唯一学生对象的引用。迭代变量和studentDTOList两者都引用相同的学生对象作为studentDTO方法的参数。

And change the loop to

并将循环更改为

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

However, methods like ChangeNameare unusual. The way to go is to encapsulate the field in a property

然而,像这样ChangeName的方法是不寻常的。要走的路是将字段封装在一个属性中

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

You can then change the loop to

然后您可以将循环更改为

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


EDIT

编辑

In a comment you say that you have to change many fields. In that case it would be okay to have a method UpdateStudentthat would do all the changes; however I still would keep the properties.

在评论中,您说您必须更改许多字段。在那种情况下,可以使用一种方法UpdateStudent来完成所有更改;但是我仍然会保留这些属性。

If there is no additional logic in the properties besides passing through a value, you can replace them by the handy auto-implemented properties.

如果属性中除了传递值之外没有其他逻辑,您可以将它们替换为方便的自动实现的属性。

public string Name { get; set; }

In that case you would have to drop the field name.

在这种情况下,您将不得不删除该字段name

回答by Jon Skeet

You're not actually changing the object that you're referring to anyway, so you can just use:

无论如何,您实际上并没有更改您所指的对象,因此您可以使用:

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

Or still call a method:

或者仍然调用一个方法:

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

In both cases, the code doesn't change the value of the iteration variable (student) so it's okay.

在这两种情况下,代码都不会更改迭代变量 ( student)的值,所以没问题。

But your original example doesn't compile anyway - an iteration variable introduced by a foreachloop is read-only.

但是您的原始示例无论如何都无法编译 - 循环引入的迭代变量foreach是只读的。