【发布时间】:2019-11-14 10:26:41
【问题描述】:
我有以下代码:
newsplit.ToList().ForEach(x => x = "WW");
我希望列表中的所有元素现在都是“WW”,但它们仍然是原始值。怎么来的?我必须做些什么不同的事情?
【问题讨论】:
我有以下代码:
newsplit.ToList().ForEach(x => x = "WW");
我希望列表中的所有元素现在都是“WW”,但它们仍然是原始值。怎么来的?我必须做些什么不同的事情?
【问题讨论】:
假设newsplit 是IEnumerable<string>,你想要:
newsplit = newsplit.Select(x => "WW");
您当前拥有的代码相当于以下代码:
foreach(string x in newsplit.ToList()) {
AssignmentAction(x);
}
...
public static void AssignmentAction(string x) {
x = "WW";
}
由于 C# 的按值传递语义和字符串的不变性,此方法不会修改 x。
【讨论】:
其他答案已经解释了为什么您当前的代码不起作用。这是一个可以修复它的扩展方法:
// 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]);
}
}
然后像这样使用:
newsplit.ModifyEach(x => "WW");
这适用于IList<T> 的任何实现,例如数组和List<T>。如果您需要它与任意 IEnumerable<T> 一起工作,那么您就有问题了,因为序列本身可能不可变。
当然,使用Select() 是一种更实用的方法,但有时改变现有集合是值得做的...
【讨论】:
ForEach 将允许您操作 IEnumerable 的元素,但不会更改元素的引用。
即,这会将 IEnumerable 中每个元素的 Foo 属性设置为字符串 "WW":
newsplit.ToList().ForEach(x => x.Foo = "WW");
但是,您将无法修改 IEnumerable 本身的值。
【讨论】:
这是因为 LINQ 表达式正在创建 Anonymous Types,而这些是只读的。他们不能被分配到。此外,在每个循环的标准中,您不能将其分配给正在枚举的集合。试试:
foreach (var item in newsplit)
{
item = "this won't work";
}
【讨论】:
你可以这样写:
newsplit = newsplit.Select(x => "WW").ToList();
【讨论】: