更改List <t> .ForEach ForEach方法</t>中的元素值

时间:2009-07-21 16:16:53

标签: c# linq c#-3.0

我有以下代码:

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

我希望列表中的所有元素现在都是“WW”,但它们仍然是原始值。怎么会?我该怎么办?

5 个答案:

答案 0 :(得分:35)

假设newsplitIEnumerable<string>,您需要:

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

您目前拥有的代码等同于以下内容:

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

...

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

由于C#的pass-by-value语义和字符串的不变性,此方法不会修改x

答案 1 :(得分:18)

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

// 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()是一种更具功能性的方法,但有时会改变现有的 值得...

答案 2 :(得分:2)

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

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

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

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

答案 3 :(得分:1)

您可以这样写:

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

答案 4 :(得分:0)

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

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