为什么IList <T>上的.ForEach()而不是IEnumerable <T>?

Ole*_*ema 52 c# linq ienumerable list c#-3.0

可能重复:
为什么IEnumerable接口上没有ForEach扩展方法?

我注意到在编写LINQ-y代码时,.ForEach()是一个很好用的习惯用法.例如,这是一段代码,它接受以下输入,并产生这些输出:

{ "One" } => "One"
{ "One", "Two" } => "One, Two"
{ "One", "Two", "Three", "Four" } => "One, Two, Three and Four";
Run Code Online (Sandbox Code Playgroud)

和代码:

private string InsertCommasAttempt(IEnumerable<string> words)
{
    List<string> 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();
}
Run Code Online (Sandbox Code Playgroud)

请注意第二行到最后一行的.ForEach()之前插入的.ToList().

为什么.ForEach()不能作为IEnumerable的扩展方法?有了这样的例子,它看起来很奇怪.

提前致谢,

戴夫

Jus*_* R. 39

根据Eric Lippert的说法,这主要是出于哲学原因.你应该阅读整篇文章,但就我而言,这里是要点:

出于两个原因,我在哲学上反对提供这样的方法.

第一个原因是这样做违反了所有其他序列运算符所基于的函数式编程原则.显然,调用此方法的唯一目的是引起副作用.

表达式的目的是计算一个值,而不是引起副作用.声明的目的是产生副作用.这个东西的调用站点看起来很像一个表达式(但是,诚然,由于该方法是void返回的,因此表达式只能用于"语句表达式"上下文.)

对我来说,制作唯一一个仅对其副作用有用的序列运算符并不合适.

第二个原因是,这样做会增加语言的新代表性能力.

  • 是的,如果我们每个人都可以设计出数百万其他人使用的编译器:) (12认同)
  • 如果您自己的个人编程偏好可能会影响数百万其他人,那会不会很好?这种"Eric Lippert"挥舞着这样的力量...... (6认同)

Sam*_*uel 38

因为ForEach(Action)存在之前IEnumerable<T>存在.

由于没有添加其他扩展方法,可以假设C#设计者认为它是一个糟糕的设计并且更喜欢foreach构造.


编辑:

如果你想要你可以创建自己的扩展方法,它不会覆盖a的那个,List<T>但它适用于任何其他实现的类IEnumerable<T>.

public static class IEnumerableExtensions
{
  public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
  {
    foreach (T item in source)
      action(item);
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 不,但它表明他们觉得这个方法是错误的,而不喜欢foreach结构. (3认同)

Joe*_*orn 5

因为ForEach()在IEnumerable上只是每个循环的正常,如下所示:

for each T item in MyEnumerable
{
    // Action<T> goes here
}
Run Code Online (Sandbox Code Playgroud)