为什么.ForEach()在IList上而不是IEnumerable上?
为什么.ForEach()在IList上而不是IEnumerable上?
这个问题已经有答案了:
可能是重复问题:
我注意到在写 LINQ 代码时,.ForEach()
是一个不错的习惯用法。例如,以下是一个代码片段,它将以下输入产生以下输出:
{ "One" } => "One" { "One", "Two" } => "One, Two" { "One", "Two", "Three", "Four" } => "One, Two, Three and Four";
而这就是代码:
private string InsertCommasAttempt(IEnumerable words) { List wordList = words.ToList(); StringBuilder sb = new StringBuilder(); var wordsAndSeparators = wordList.Select((string word, int pos) => { if (pos == 0) return new { Word = word, Leading = string.Empty }; if (pos == wordList.Count - 1) return new { Word = word, Leading = " and " }; return new { Word = word, Leading = ", " }; }); wordsAndSeparators.ToList().ForEach(v => sb.Append(v.Leading).Append(v.Word)); return sb.ToString(); }
请注意,倒数第二行的 .ForEach()
前加入了 .ToList()
。
为什么在 IEnumerable
上没有 .ForEach()
作为扩展方法?对于像这样的示例,这似乎很奇怪。
admin 更改状态以发布 2023年5月20日
根据Eric Lippert的说法,这主要出于哲学的原因。你应该阅读整个帖子,但就我而言,以下是要点:\n\n 我在哲学上反对提供这样的方法,有两个原因。\n\n 第一个原因是这样做违反了所有其他序列操作符所基于的函数式编程原则。显然,调用此方法的唯一目的是引起副作用。\n\n表达式的目的是计算一个值,而不是引起副作用。语句的目的是引起副作用。这个东西的调用站点看起来非常像一个表达式(尽管可以承认,由于该方法没有返回值,该表达式只能在“语句表达式”上下文中使用)。\n\n在我的思想中,使唯一一个仅仅有副作用有用的序列运算符并不合适。\n\n第二个原因是这样做并没有为语言增加任何新的表现力。
因为 ForEach(Action)
在 IEnumerable
存在之前就存在了。
由于它没有与其他扩展方法一起添加,可以假设C#设计师认为这是一种糟糕的设计,并且更喜欢 foreach
结构。
编辑:
如果您想要,可以创建自己的扩展方法,它不会覆盖 List
的方法,但对于实现 IEnumerable
接口的任何其他类都适用。
public static class IEnumerableExtensions { public static void ForEach(this IEnumerable source, Action action) { foreach (T item in source) action(item); } }