Вы можете использовать IEnumerable.Intersect.
var z = a.Intersect(b);
что вероятно будет более эффективным, чем ваше текущее решение.
обратите внимание, что вы упустили одну важную информацию - независимо от того, упорядочены ли списки или нет. Если это пара вложенных циклов, которые проходят по каждому входному массиву ровно один раз, то каждый из них может быть быстрее - и немного веселее писать.
Редактировать
В ответ на ваш комментарий по поводу заказа:
первый удар по циклу - ему понадобится небольшая настройка от вашего имени, но он работает для ваших начальных данных.
int j = 0;
foreach (var i in a)
{
int x = b[j];
while (x < i)
{
if (x == i)
{
z.Add(b[j]);
}
j++;
x = b[j];
}
}
это то место, где вам нужно добавить несколько юнит-тестов;)
Редактировать
И последнее замечание - вполне возможно, что Linq может использовать SortedList для очень эффективного выполнения этого пересечения, если производительность является проблемой, стоит протестировать различные решения. Не забудьте учесть сортировку, если вы загружаете данные неупорядоченным образом.
Одно окончательное редактирование , потому что там были кое-что, и люди могут использовать вышеупомянутое без надлежащей отладки. Я выкладываю более позднюю версию здесь:
int j = 0;
int b1 = b[j];
foreach (var a1 in a)
{
while (b1 <= a1)
{
if (b1 == a1)
z1.Add(b[j]);
j++;
if (j >= b.Count)
break;
b1 = b[j];
}
}