Foreach (... in...) или .ForEach(); вот в чем вопрос
Возможный дубликат:
С# foreach vs functional each
Это вопрос о кодировании для удобочитаемости.
У меня есть XDocument
и List<string>
имена элементов, которые содержат конфиденциальную информацию, которую мне нужно замаскировать (замените символом подчеркивания в этом примере).
XDocument xDoc;
List<string> propertiesToMask;
Это можно записать двумя способами, используя традиционные циклы foreach
или используя методы .ForEach
с синтаксисом lamba.
foreach (string propertyToMask in propertiesToMask)
{
foreach (XElement element in xDoc.Descendants(propertyToMask))
{
element.SetValue(new string('_', element.Value.Length));
}
}
или
propertiesToMask
.ForEach(propertyToMask => xDoc.Descendants(propertyToMask).ToList()
.ForEach(element => element.SetValue(new string('_', element.Value.Length))));
Какой подход, по вашему мнению, является наиболее читаемым и почему? Если вы предпочитаете второй пример, как бы вы представили его для максимальной читаемости?
Ответы
Ответ 1
foreach (string propertyToMask in propertiesToMask)
{
foreach (XElement element in xDoc.Descendants(propertyToMask))
{
element.SetValue(new string('_', element.Value.Length));
}
}
Поскольку интервал делает его очень простым для сканирования. Во-вторых, это намного глубже, и я должен его прочитать.
Ответ 2
Эрик Липперт имеет хорошую запись об этом в своем блоге. Подводя итог, сама задача, выполняемая ForEach
, заключается в создании побочных эффектов, которые могут быть нежелательными для функционального стиля программирования на С#.
Ответ 3
Я предпочитаю первую по трем причинам.
Во-первых, он более эффективен (во втором у вас есть дополнительные вызовы ToList()).
Во-вторых, это более читаемо, на мой взгляд.
Наконец, я бы рекомендовал читать сообщение Эрика Липперта на эту тему. Есть философские причины, чтобы избежать List<T>.ForEach
, поскольку это целая цель - вызвать побочные эффекты, даже если он имеет функциональный стиль.
Ответ 4
Традиционный способ имеет большое преимущество, что его можно легко отладить. Но я лично предпочел бы подход ForEach()
в этом случае. Тот факт, что трудно отлаживать код, написанный на беглоте, по-моему, является недостатком доступных инструментов, а не стиля кодирования. В моем личном опыте частота ошибок в таких методах очень низкая, поэтому это не очень большая проблема.
Я бы написал некоторые методы расширений, дающие следующий код.
propertiesToMask
.SelectMany(property => document.Descendants(property))
.ForEach(element => element.MaskValue());
Ответ 5
Первый может быть изменен во время работы отладчика, а Visual Studio позволяет продолжить отладку. После изменения варианта .ForEach вам необходимо перезапустить сеанс отладки и перекомпилировать, поскольку он содержит лямбда-выражение (VS 2008)
Ответ 6
Вот действительно субъективный ответ:
Я действительно не согласен с философскими соображениями, которые не нравятся. Может быть, это моя нехватка информатики, я не знаю.
Для меня второй набор кода легче читать и выглядит намного менее запутанным. Как уже отмечали другие, ToList() выглядит неудачно, но мне все равно выглядит лучше.
Мне нравится решение Daniel Brückner еще лучше. Это кажется лучше, чем любое из других предлагаемых решений.