如果您IList<T>
是一个数组(T[]
),那么你对他们Array.ForEach方法类似于ForEach
上List<T>
。您可以为自定义IList<T>
或IEnumerable<T>
或任何您喜欢的任何方式创建扩展方法。
public static void ForEach<T>(this IList<T> list, Action<T> action)
{
foreach (T t in list)
action(t);
}
你只需要警惕原始集合中的对象将被修改的事实,但我想命名确实意味着这一点。
--------------------------------------------- -------------------------------------------------- -------------------------------------
我宁愿打电话:
people.Where(p => p.Tenure > 5)
.Select(p => p.Nationality)
.ForEach(n => AssignCitizenShip(n);
比
foreach (var n in people.Where(p => p.Tenure > 5).Select(p => p.Nationality))
{
AssignCitizenShip(n);
}
如果这样你就可以IEnumerable
创建扩展方法。请注意,终止呼叫ForEach
会执行Linq
查询。如果你不想要的话,可以使用yield
语句并返回一个IEnumerable<T>
回来推迟太:
public static IEnumerable<T> ForEach<T>(this IEnumerable<T> list, Action<T> action)
{
foreach (T t in list)
{
action(t);
yield return t;
}
}
这解决了副作用的问题,但我个人喜欢一个名为ForEach
最终执行调用方法。
--------------------------------------------- -------------------------------------------------- ------------------------------------
为了解决有关偏好的相反观点,here is a better link来自Eric Lippert的比this。要引用他的话:
“第一个原因是,这样做违反了函数式编程的所有其他序列运营商基于 原则 显然,这种方法的调用的唯一目的是使侧 效果。表达式的目的是为了计算一个值,而不是对 造成副作用。一个语句的目的是引起一个方面 效应。这个东西的调用网站看起来很像一个 表达式(虽然,诚然,由于该方法是无效的返回, 该表达式只能在“语句表达式” 上下文中使用)。它不是很好与我作出唯一的 序列运算符,这只对其副作用有用。
第二个原因是,这样做增加了零新表象 电源语言”
埃里克并没有说这是一个坏的事情 - 只是哲学的决定不包括背后的原因在Linq
构造默认情况下,如果你认为IEnumerable
上的函数不应该对内容起作用,那么不要这样做,我个人不介意,因为我很清楚它的作用。其他方法会导致集合类的副作用,如果需要,我可以进入函数并调试它,下面是另一个从Linq
本身。
people.Where(p => p.Tenure > 5)
.Select(p => p.Nationality)
.AsParallel()
.ForAll(n => AssignCitizenShip(n);
正如我所说,这些没有什么不好。它只是个人的喜好。 我不会将它用于嵌套的foreach
,或者它包含多于一行的代码以在foreach
循环内执行,因为这是不可读的。但是我发布了一个简单的例子,我喜欢它。看起来干净简洁。
编辑:见BTW性能链接:Why is List<T>.ForEach faster than standard foreach?
为什么你不能使用foreach循环? – BoltClock
这被认为是一个坏主意,你究竟在获得什么?代码不会更短... - http://blogs.msdn.com/b/mazhou/archive/2011/09/21/why-no-foreach-method-on-ienumerable-interfaces.aspx – Maarten
你可以添加ForEach作为IList的扩展方法。 –