13

可能的重复:
C# foreach 与功能各自

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

我有一个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))));

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

4

6 回答 6

14

Eric Lippert在他的博客上有一篇很好的文章。总而言之,所完成的任务ForEach就是产生副作用,这可能与 C# 中的函数式编程风格无关。

于 2010-02-09T16:15:13.297 回答
14
foreach (string propertyToMask in propertiesToMask)
{
    foreach (XElement element in xDoc.Descendants(propertyToMask))
    {
        element.SetValue(new string('_', element.Value.Length));
    }
}

因为间距使得扫描变得非常简单。第二个很混乱,我必须真正阅读它。

于 2010-02-09T16:15:50.037 回答
4

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

首先,它更高效(其次,您有额外的 ToList() 调用)。

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

最后,我推荐阅读Eric Lippert 关于这个主题的博文。 有哲学上的理由要避免List<T>.ForEach,因为它的全部目的是引起副作用,即使它具有功能风格。

于 2010-02-09T16:17:18.860 回答
4

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

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

propertiesToMask
   .SelectMany(property => document.Descendants(property))
   .ForEach(element => element.MaskValue());
于 2010-02-09T16:24:25.403 回答
1

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

于 2010-02-09T16:21:37.163 回答
0

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

我不太同意不喜欢 .ForEach 背后的哲学推理。也许是我缺乏计算机科学背景,我不知道。

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

我更喜欢 Daniel Brückner 的解决方案。它似乎比任何其他提议的解决方案都好。

于 2010-02-09T16:20:24.110 回答