У меня есть следующий код:
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";
}
Этот метод не будет изменять x
из-за семантики pass-by-значения С# и неизменяемости строк.
Другие ответы объяснили, почему ваш текущий код не работает. Здесь используется метод расширения, который бы исправил его:
// 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()
- более функциональный подход, но иногда мутация существующей коллекции стоит делать...
The ForEach позволит вам манипулировать элементами IEnumerable, но не изменять ссылку элемента.
т.е. это установит свойство Foo
каждого элемента в IEnumerable в строку "WW"
:
newsplit.ToList().ForEach(x => x.Foo = "WW");
Однако вы не сможете изменять значения внутри самого IEnumerable.
Это потому, что выражение LINQ создает Анонимные типы, и они доступны только для чтения. Они не могут быть назначены. Кроме того, в стандарте для каждого цикла вы не можете назначить перечислимую коллекцию. Попробуйте:
foreach (var item in newsplit)
{
item = "this won't work";
}