foreach(… in …)或.ForEach(); 这就是问题

可能重复:
C#foreach vs functional each

这是关于编码可读性的问题。

我有一个XDocument和一个List包含我需要屏蔽的敏感信息的元素名称(在本例中用下划线替换)。

 XDocument xDoc; List propertiesToMask; 

这可以用两种方式编写,使用传统的foreach循环,或使用带有lamba语法的.ForEach方法。

 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)))); 

您认为哪种方法最易读,为什么? 如果您更喜欢第二个示例,您将如何呈现它以获得最大可读性?

 foreach (string propertyToMask in propertiesToMask) { foreach (XElement element in xDoc.Descendants(propertyToMask)) { element.SetValue(new string('_', element.Value.Length)); } } 

因为间距使得扫描非常简单。 第二个是混乱的,我必须实际阅读它。

Eric Lippert 在他的博客上有一个很好的参与 。 总而言之, ForEach完成的任务是产生副作用,这可能不是C#中编程function样式的理想选择。

出于三个原因,我非常喜欢第一个。

首先,它更有效(第二,你有额外的ToList()调用)。

其次,在我看来,它更具可读性。

最后,我建议阅读Eric Lippert关于这个主题的博客文章。 有哲学上的理由要避免List.ForEach ,因为它的全部目的是引起副作用,即使它具有function风格。

传统方式具有可以轻松调试的巨大优势。 但在这种情况下,我个人更喜欢ForEach()方法。 在我看来,用流利的代码编写代码很难调试的情况是可用工具的缺陷,而不是编码风格。 根据我的个人经验,这种方法的错误率非常低,因此它不是一个很大的问题。

我会写一些扩展方法,产生以下代码。

 propertiesToMask .SelectMany(property => document.Descendants(property)) .ForEach(element => element.MaskValue()); 

第一个可以在调试器运行时更​​改,Visual Studio允许您继续调试。 更改.ForEach变体后,您必须重新启动调试会话并重新编译,因为它包含一个lambda表达式(VS 2008)

这是一个非常主观的答案:

我不同意不喜欢的哲学推理。每个人。 也许这是我缺乏计算机科学背景,我不知道。

对我来说,第二组代码更容易阅读,看起来更不容易。 正如其他人所提到的,ToList()有点不幸,但它对我来说仍然看起来更好。

我更喜欢DanielBrückner的解决方案。 它似乎比其他任何提出的解决方案都要好。