据我所见,ForEach
方法仅适用于List
class。
为什么?我认为ForEach
没有理由不让任何实现IEnumerable
/ IEnumerator
接口的类可用,如果你需要执行一个小动作,这是一个非常有用的方法(1 line比1行+ 2样板foreach语法更可读...)。
更新:我会澄清我的问题。在序列中包含ForEach
是完全正确的理由。 不在所有序列中包含ForEach
都有充分的理由。
但我无法理解为什么ForEach
会被包含在一些序列中。
答案 0 :(得分:23)
见Eric Lippert的帖子:"foreach" vs "ForEach"
很多人都问我原因 没有微软提供的 “ForEach”序列运算符扩展 方法。 List类有这样的 方法当然已经存在,但是有 没有理由不这样做 作为扩展方法创建 所有序列。
...
但我们可以在这里更深入一点。我是 哲学上反对提供 这种方法有两个原因。
...
第一个原因就是这样做 违反了函数式编程 所有其他顺序的原则 运营商是基于。显然是 唯一目的是调用此方法 是造成副作用。
...
第二个原因就是这样做 增加零代表性能力 语言。
...
嗯,VS Languages团队没有 对所发生的事情有任何影响 名单。我亲自找到了 List上的“ForEach”方法 为所有人带来哲学上的麻烦 同样的理由,我会找到一个 IEnumerable上的扩展方法 令人不安。 (和VSL团队一样 控制那个。)一个减轻 因素是List清楚 旨在成为一个可变的, 无副作用的数据结构, 所以使用变异它的表达式 似乎稍微不那么糟糕。 - 埃里克
答案 1 :(得分:7)
你是对的,该方法在List类中定义。但是,它很容易创建一个做同样事情的扩展方法。
public static void ForEach<T>(this IEnumerable<T> enumerable, Action<T> action)
{
foreach (var t in enumerable)
action(t);
}
答案 2 :(得分:2)
正确。但是,如果你想利用ForEach循环的优势,有一个名为“ToList”的方法,如下所示,用于将数组转换回List。
String[] array = new String[3];
List<String> list = array.ToList<String>();
答案 3 :(得分:2)
从技术上讲,使用.NET 3.5,您可以这样做:(您需要包含System.Linq)
IEnumerable<string> a = ...
a.All(i => { DoSomethingWith(i); return true; });
答案 4 :(得分:0)
以下是支持异常处理的.ForEach()扩展方法的不同版本。这将捕获所有的exeptions,所以你可能想要重新抛出那些你没有处理的。
(这是为了与VS 2010一起使用而编写的...如果您使用以前的版本,则可能需要从方法签名中删除 = null )
public static void SafeForEach<T>(this IEnumerable<T> input,
Action<T> action,
Action<T, Exception> faultAction = null)
{
if (input == null || action == null)
return;
foreach (var item in input)
try
{
action(item);
}
catch (Exception ex)
{
if (faultAction == null)
Debug.WriteLine(ex);
else
faultAction(item, ex);
}
}