[править]: уточнить; это полезно в общем контексте LINQ / IEnumerable<T>
, где вы не можете использовать индексатор, потому что a: он не существует в перечислимом и b: вы не можете гарантировать, что вы может читать данные более одного раза. Поскольку в ОП упоминаются лямбды, оказывается, что LINQ может быть не слишком далеко (и да, я понимаю, что LINQ и лямбды не совсем одно и то же).
Похоже, вам нужен пропавший оператор Zip
; Вы можете подделать его:
static void Main()
{
int[] left = { 1, 2, 3, 4, 5 };
string[] right = { "abc", "def", "ghi", "jkl", "mno" };
// using KeyValuePair<,> approach
foreach (var item in left.Zip(right))
{
Console.WriteLine("{0}/{1}", item.Key, item.Value);
}
// using projection approach
foreach (string item in left.Zip(right,
(x,y) => string.Format("{0}/{1}", x, y)))
{
Console.WriteLine(item);
}
}
// library code; written once and stuffed away in a util assembly...
// returns each pais as a KeyValuePair<,>
static IEnumerable<KeyValuePair<TLeft,TRight>> Zip<TLeft, TRight>(
this IEnumerable<TLeft> left, IEnumerable<TRight> right)
{
return Zip(left, right, (x, y) => new KeyValuePair<TLeft, TRight>(x, y));
}
// accepts a projection from the caller for each pair
static IEnumerable<TResult> Zip<TLeft, TRight, TResult>(
this IEnumerable<TLeft> left, IEnumerable<TRight> right,
Func<TLeft, TRight, TResult> selector)
{
using(IEnumerator<TLeft> leftE = left.GetEnumerator())
using (IEnumerator<TRight> rightE = right.GetEnumerator())
{
while (leftE.MoveNext() && rightE.MoveNext())
{
yield return selector(leftE.Current, rightE.Current);
}
}
}