Изменение значения элемента в методе List <T>.ForEach ForEach - PullRequest
23 голосов
/ 21 июля 2009

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

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

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

Ответы [ 4 ]

35 голосов
/ 21 июля 2009

Предполагая, что 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 из-за семантики передачи по значению C # и неизменности строк.

18 голосов
/ 21 июля 2009

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

// 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 голосов
/ 21 июля 2009

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

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

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

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

0 голосов
/ 21 июля 2009

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

    foreach (var item in newsplit)
    {
        item = "this won't work";
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...