C# 更改 List<T>.ForEach ForEach 方法中的元素值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1160217/
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-06 09:38:46  来源:igfitidea点击:

Changing element value in List<T>.ForEach ForEach method

c#linqc#-3.0

提问by Jon

I have the following code:

我有以下代码:

newsplit.ToList().ForEach(x => x = "WW");

I would expect that all elements in the list are now "WW" but they are still the original value. How come? What do I have to do different?

我希望列表中的所有元素现在都是“WW”,但它们仍然是原始值。怎么来的?我必须做什么不同的?

采纳答案by jason

Assuming that newsplitis an IEnumerable<string>, you want:

假设这newsplit是一个IEnumerable<string>,你想要:

newsplit = newsplit.Select(x => "WW");

The code that you currently have is equivalent to the following:

您当前拥有的代码等效于以下内容:

foreach(string x in newsplit.ToList()) {
    AssignmentAction(x);
}

...

public static void AssignmentAction(string x) {
    x = "WW";
}

This method won't modify xbecause of the pass-by-value semantics of C# and the immutability of strings.

x由于 C# 的按值传递语义和字符串的不变性,此方法不会修改。

回答by Dan Diplo

It's because the LINQ expression is creating Anonymous Types, and these are read-only. They can't be assigned to. Also, in a standard for each loop you cannot assign to a collection that is being enumerated. Try:

这是因为 LINQ 表达式正在创建Anonymous Types,而这些是只读的。他们不能被分配到。此外,在每个循环的标准中,您不能分配给正在枚举的集合。尝试:

    foreach (var item in newsplit)
    {
        item = "this won't work";
    }

回答by AgileJon

The ForEach will allow you to manipulate the elements of the IEnumerable, but not change the reference of the element.

ForEach 将允许您操作 IEnumerable 的元素,但不能更改元素的引用。

ie, this would set a Fooproperty of each element in the IEnumerable to the string "WW":

即,这会将FooIEnumerable 中每个元素的属性设置为字符串"WW"

newsplit.ToList().ForEach(x => x.Foo = "WW");

However, you won't be able to modify the values inside the IEnumerable itself.

但是,您将无法修改 IEnumerable 本身内部的值。

回答by Jon Skeet

Other answers have explained why your current code doesn't work. Here's an extension method which would fix it:

其他答案解释了为什么您当前的代码不起作用。这是一个可以修复它的扩展方法:

// Must be in a static non-nested class
public static void ModifyEach<T>(this IList<T> source,
                                 Func<T,T> projection)
{
    for (int i = 0; i < source.Count; i++)
    {
        source[i] = projection(source[i]);
    }
}

Then use like this:

然后像这样使用:

newsplit.ModifyEach(x => "WW");

That will work with any implementation of IList<T>such as arrays and List<T>. If you need it to work with an arbitrary IEnumerable<T>then you've got a problem, as the sequence itself may not be mutable.

这将适用于任何实现,IList<T>例如数组和List<T>。如果您需要它与任意对象一起工作,IEnumerable<T>那么您就会遇到问题,因为序列本身可能不可变。

Using Select()is a more functional approach of course, but sometimes mutating an existing collection isworth doing...

使用Select()当然是一种更实用的方法,但有时对现有集合进行变异值得的......

回答by Wang_TWJ

You can write like this:

你可以这样写:

newsplit = newsplit.Select(x => "WW").ToList();