Подтвердить что ты не робот

Изменение значения элемента в списке <T>. FOREach ForEach method

У меня есть следующий код:

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

Я бы ожидал, что все элементы в списке теперь "WW", но они все еще являются исходным значением. Как так? Что мне нужно делать другим?

4b9b3361

Ответ 1

Предполагая, что newsplit является IEnumerable<string>, вы хотите:

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

Код, который у вас есть в настоящее время, эквивалентен следующему:

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

...

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

Этот метод не будет изменять x из-за семантики pass-by-значения С# и неизменяемости строк.

Ответ 2

Другие ответы объяснили, почему ваш текущий код не работает. Здесь используется метод расширения, который бы исправил его:

// 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() - более функциональный подход, но иногда мутация существующей коллекции стоит делать...

Ответ 3

The ForEach позволит вам манипулировать элементами IEnumerable, но не изменять ссылку элемента.

т.е. это установит свойство Foo каждого элемента в IEnumerable в строку "WW":

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

Однако вы не сможете изменять значения внутри самого IEnumerable.

Ответ 4

Это потому, что выражение LINQ создает Анонимные типы, и они доступны только для чтения. Они не могут быть назначены. Кроме того, в стандарте для каждого цикла вы не можете назначить перечислимую коллекцию. Попробуйте:

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