免责声明:这个问题是出于个人的好奇心,而非实际需要完成的事情。所以我的例子将会做作。 尽管如此,我认为这个问题很可能会突然出现。
假设我们正在使用Zip迭代两个序列,调用一个void方法,如果发现该对的一个项目与另一个项目不同(因此丢弃任何返回值),则该方法会抛出异常。这里的要点不是该方法抛出异常,而是返回void。
换句话说,我们在两个集合中做了ForEach
(顺便说一下,我知道Eric Lippert thinks about ForEach
是什么,并且完全同意他并且从不使用它。)
现在,Zip
想要一个Func<TFirst, TSecond, TResult>
,所以当然传递相当于Action<TFirst, TSecond>
的内容是行不通的。
我的问题是:是否存在比这更好的惯用方法(即返回虚拟值)?
var collection1 = new List<int>() { ... };
var collection2 = new List<int>() { ... };
collection1.Zip(collection2, (first, second) =>
{
VoidMethodThatThrows(first, second);
return true;
});
答案 0 :(得分:20)
使用Zip()
将项目投放到对象中,然后以您选择的方式执行foreach
(请执行正常foreach
循环,而不是错误 ToList / ForEach组合)。
var items = collection1.Zip(collection2, (x, y) => new { First = x, Second = y });
foreach (var item in items)
{
VoidMethodThatThrows(item.First, item.Second);
}
从C#7.0开始,改进的元组支持和解构使得它更令人愉悦。
var items = collection1.Zip(collection2, (x, y) => (x, y));
// or collection1.Zip(collection2, ValueTuple.Create);
foreach (var (first, second) in items)
{
VoidMethodThatThrows(first, second);
}
答案 1 :(得分:1)
我经常需要对两个集合中的每对执行操作。在这种情况下,Zip方法无效。
可以使用此扩展方法 ForPair :
public static void ForPair<TFirst, TSecond>(this IEnumerable<TFirst> first, IEnumerable<TSecond> second,
Action<TFirst, TSecond> action)
{
using (var enumFirst = first.GetEnumerator())
using (var enumSecond = second.GetEnumerator())
{
while (enumFirst.MoveNext() && enumSecond.MoveNext())
{
action(enumFirst.Current, enumSecond.Current);
}
}
}
因此,对于您的示例,您可以编写:
var collection1 = new List<int>() { 1, 2 };
var collection2 = new List<int>() { 3, 4 };
collection1.ForPair(collection2, VoidMethodThatThrows);