C# 使用foreach在多个列表中同时迭代(语法)

C# 使用foreach在多个列表中同时迭代(语法),c#,.net,C#,.net,嗨,有没有这样的方法: for (int i = 0; i < Math.Min(a.Count, b.Count); i++) { // Do stuff //a[i] //b[i] } 编辑 好吧,对不起,我对一些人不够清楚,所以希望这里有更好的解释 List<classA> listA = fillListA(); List<classB> listB = fillListB(); //here could be infinity m

嗨,有没有这样的方法:

for (int i = 0; i < Math.Min(a.Count, b.Count); i++)
{
    // Do stuff
    //a[i]
    //b[i]
}
编辑 好吧,对不起,我对一些人不够清楚,所以希望这里有更好的解释

List<classA> listA = fillListA();
List<classB> listB = fillListB();
//here could be infinity many lists of sometimes diffrent T types
恐怕我不能修改这样一个单词类的东西 所以我认为可以像did
ForEach(IEnumerable,Action)一样构建迭代器
但她说我被绊倒了,因为我不知道如何实施它

Static.ForEach<TSource>(IEnumerable<TSource>,IEnumerable<TSource>, ???Action<TSource,???>????)
Static.ForEach(IEnumerable,IEnumerable,?Action??)

我唯一能想到的是:

当然,如果我们没有使用
,而是使用了一种无副作用的方法,从两个元素中产生第三个值,那么您可以:

var result = list1.Zip(list2, (item1, item2) => item1.ProduceObject(item2))
                  .ToList(); // if required
您可以使用类似这样的方法(尽管仅在.NET4及更高版本中可用)

List<int> l4 = new List<int> { 1, 2, 3, 4 };
List<int> l5 = new List<int> { 5, 6, 7 };

var l4Andl5 = l4.Zip(l5, (l, m) => new { List1 = l, List2 = m });
foreach (var x in l4Andl5)
{


}
List l4=新列表{1,2,3,4};
列表l5=新列表{5,6,7};
var l4Andl5=l4.Zip(l5,(l,m)=>new{List1=l,List2=m});
foreach(L4和L5中的变量x)
{
}

您可以做
foreach
在引擎盖下所做的事情,但需要两个枚举器:

using(var e1 = list1.GetEnumerator())
using(var e2 = list2.GetEnumerator())
{
    while(e1.MoveNext() && e2.MoveNext())
    {
         var item1 = e1.Current;
         var item2 = e2.Current;

         // use item1 and item2
    }
}
为方便起见,您可以编写如下所示的扩展方法来执行操作:

public static void ZipDo<T1, T2>( this IEnumerable<T1> first, IEnumerable<T2> second, Action<T1, T2> action)
{
    using (var e1 = first.GetEnumerator())
    using (var e2 = second.GetEnumerator())
    {
        while (e1.MoveNext() && e2.MoveNext())
        {
            action(e1.Current, e2.Current);
        }
    }
}

顺便说一下,您可以将其展开以使用3个或更多列表:

public static void ZipDo<T1, T2, T3>(this IEnumerable<T1> first,
    IEnumerable<T2> second, IEnumerable<T3> third,
    Action<T1, T2, T3> action)
{
    using (var e1 = first.GetEnumerator())
    using (var e2 = second.GetEnumerator())
    using (var e3 = third.GetEnumerator())
    {
        while (e1.MoveNext() && e2.MoveNext() && e3.MoveNext())
        {
            action(e1.Current, e2.Current, e3.Current);
        }
    }
}

如果列表长度相同,也可以简单地使用局部整数变量:

List<classA> listA = fillListA();
List<classB> listB = fillListB();

var i = 0;
foreach(var itemA in listA)
{
    itemA.use(listB[i++]);
}
List listA=fillListA();
List listB=fillListB();
var i=0;
foreach(列表A中的var itemA)
{
itemA.use(listB[i++]);
}

因此无法创建某种类型的
操作
?我认为有一种方法可以编写类似于
Parallel.Foreach()
的东西,没有什么可以阻止您在这里使用Parallel.Foreach而不是Foreach语言。对不起,我遗漏了什么吗?不,我的意思是并行。Foreach您可以像Parallel.Foreach(list,item=>{//dostuff})一样编写它,其中第一个参数=ienum,第二个参数=action。所以我想我可以编写一个函数,比如
StaticClass.ForEach(Ienum,Ienum,someaction??)
你的意思是:
Parallel.ForEach(list1.Zip(list2,Tuple.Create),Tuple=>Tuple.Item1.use(Tuple.Item2))请记住,这只是并行调用操作,而不是枚举源或将它们压缩在一起。
公共静态void ForEach(IEnumerable source1,IEnumerable source2,Action body){ForEach(source1.Zip中的var tuple(source2,tuple.Create)){body(tuple.Item1,tuple.Item2);}
?不完全是因为类型(a)!=typeof(b)也可以存在一个列表c、d,…这里类型不重要,第二个列表可以是string类型。你的答案与Ani的答案相比有什么优势吗?@WiiMaxx你可以将这种方法扩展到3个或更多列表(请参见编辑),但如果你只需要压缩2个列表,它们大致相同——实际上没有性能或可读性差异。如果一个列表比另一个短呢?“iterrate不就到此为止了吗?”克里斯,对不起,我晚了才注意到你的问题。是的,它将停止迭代,这通常是您想要的,并且与Linq的Zip方法一致。但是,如果要继续,可以将“&&MoveNext”替换为“| | MoveNext”。然后,您需要决定对完成的枚举器的当前项使用什么,例如使用默认值(T)。
public static void ZipDo<T1, T2>( this IEnumerable<T1> first, IEnumerable<T2> second, Action<T1, T2> action)
{
    using (var e1 = first.GetEnumerator())
    using (var e2 = second.GetEnumerator())
    {
        while (e1.MoveNext() && e2.MoveNext())
        {
            action(e1.Current, e2.Current);
        }
    }
}
list1.ZipDo(list2, (i1,i2) => i1.Use(i2));
public static void ZipDo<T1, T2, T3>(this IEnumerable<T1> first,
    IEnumerable<T2> second, IEnumerable<T3> third,
    Action<T1, T2, T3> action)
{
    using (var e1 = first.GetEnumerator())
    using (var e2 = second.GetEnumerator())
    using (var e3 = third.GetEnumerator())
    {
        while (e1.MoveNext() && e2.MoveNext() && e3.MoveNext())
        {
            action(e1.Current, e2.Current, e3.Current);
        }
    }
}
public static void ZipAll<T>(this IEnumerable<IEnumerable<T>> all, Action<IEnumerable<T>> action)
{
    var enumerators = all.Select(e => e.GetEnumerator()).ToList();
    try
    {
        while (enumerators.All(e => e.MoveNext()))
            action(enumerators.Select(e => e.Current));
    }
    finally
    {
        foreach (var e in enumerators) 
            e.Dispose();
    }
}
var lists = new[] {
     new[]{ 1, 1, 1 }, 
     new[]{ 2, 2, 2 }, 
     new[]{ 3, 3, 3 }};

lists.ZipAll(nums => Console.WriteLine(nums.Sum()));
// 6
// 6
// 6
List<classA> listA = fillListA();
List<classB> listB = fillListB();

var i = 0;
foreach(var itemA in listA)
{
    itemA.use(listB[i++]);
}