使用带有没有返回值的闭包的LINQ> Zip

时间:2012-06-25 13:30:39

标签: c# linq func

免责声明:这个问题是出于个人的好奇心,而非实际需要完成的事情。所以我的例子将会做作。 尽管如此,我认为这个问题很可能会突然出现。

假设我们正在使用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;
});

2 个答案:

答案 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);