咨询区
Cameron MacFarland:
为什么 IEnumerable
接口没有 ForEach
扩展方法?我观察到能获取 ForEach 方法的类是 List<>
,有谁知道这么设计的原因吗,是为了性能?
回答区
aku:
ForEach
方法其实在 Linq 之前就已经存在了,如果这时候在 IEnumerable 上添加 ForEach 扩展方法的话会出现什么结果呢?大家应该知道扩展方法的优先级是低于同名的非扩展方法,这就意味着 IEnumerable 下的 ForEach 永远得不到调用。
如果你真的想要这个功能,可以自己实现一个。
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{foreach (T element in source) action(element);
}
leppie:
大多数 Linq 扩展方法都会返回 result,但 ForEach 这种不返回的扩展方法并不适合在这种模式中。
Martijn:
你可以使用链式延迟的 Select
来替换 ForEach
, 比如下面这样。
IEnumerable<string> people = new List<string>(){"alica", "bob", "john", "pete"};
people.Select(p => { Console.WriteLine(p); return p; });
如果要立即执行的话,可以再调用 Count()
,据我所知这是触发迭代最小代价的方法,当然你可以调用你需要的立即执行方法。
不过我倒希望下面的扩展方法被引入到标准类库中。
static IEnumerable<T> WithLazySideEffect(this IEnumerable<T> src, Action<T> action) {return src.Select(i => { action(i); return i; } );
}
上面的代码等价于 foreach,不过是链式延迟的。
点评区
Linq 不提供 ForEach 扩展方法,我感觉是设计者故意为之的,Linq 的一个强大特性在于可链式,可延迟,它和 ForEach 中间还差了一个 ToList,也许手工 ToList 可以让代码意图更明显吧,比如:
static void Main(string[] args){IEnumerable<Person> list = new List<Person>();list.Where(v => v.Name == "xxx").ToList().ForEach(m => Console.WriteLine(m.Name));}
当然你不认同这种理念也没关系,很多的 Linq 扩展库也不认同,它们就直接提供了 ForEach,比如:MoreLinq https://github.com/morelinq/
原文链接:https://stackoverflow.com/questions/101265/why-is-there-no-foreach-extension-method-on-ienumerable#101303