В дополнение к замечательным постам Эрика и Барта, вот реализация с использованием операторов System.Linq 3.5:
public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult> (
this IEnumerable<TFirst> first,
IEnumerable<TSecond> second,
Func<TFirst, TSecond, TResult> resultSelector)
{
return from aa in a.Select((x, i) => new { x, i })
join bb in b.Select((y, j) => new { y, j })
on aa.i equals bb.j
select resultSelector(aa.x, bb.y);
}