#c_sharp #циклы
Можно ли узнать, используя foreach, что текущая итерация последняя?
Ответы
Ответ 1
Самый простой способ - добавить переменную с инкрементом на каждой итерации и проверять её соответствие свойству Count контейнера. Однако в этом случае цикл foreach фактически превращается в обычный for. При этом foreach заточен на прогон по всем элементам и выполнения одинаковых действий вне зависимости от позиции элемента. Если подобный вопрос у Вас возник, то значит что-то не так с дизайном. Лучше использовать обычный for.Ответ 2
Если очень нужно, вот вам универсальный extension-метод: struct Entry{ public T Value; public bool IsFirst; public bool IsLast; } static class EnumerableExtensions { public static IEnumerable > WithFirstLast (this IEnumerable seq) { using (var en = seq.GetEnumerator()) { if (en.MoveNext()) { bool isFirst = true; Entry entry = new Entry (); do { entry.Value = en.Current; entry.IsFirst = isFirst; entry.IsLast = !en.MoveNext(); yield return entry; isFirst = false; } while (!entry.IsLast); } } } } Пользоваться так: foreach (var v in new[] { 1, 2, 3, 4, 5 }.WithFirstLast()) { if (v.IsFirst) Console.Write("First: "); if (v.IsLast) Console.Write("Last: "); Console.WriteLine(v.Value); } Этот алгоритм по сути изложен в более раннем ответе @Qwertiy. У меня добавлен лишь extension-метод. Ответ 3
В общем случае - никак. Цикл foreach использует протокол интерфейса IEnumerator - а тот не позволяет узнать о наличии следующей итерации кроме как попытавшись начать ее. В частном случае можно сделать ToList или ToArray, после чего воспользоваться циклом for. Или можно попытаться переписать алгоритм так, чтобы проверка на последнюю итерацию не требовалась.Ответ 4
Можно самому сохранять значение во внешнюю переменную и запаздывать на один элемент: http://ideone.com/Fz16u8 using System; public class Test { public static void Main() { var items = new int[] {1, 2, 3, 4, 5, 6, 7}; int item = 0; foreach(var x in items) { Console.WriteLine(item); item = x; } Console.WriteLine("{0} is the last one", item); } } Ещё можно развернуть цикл foreach руками и внести в него пару изменений: http://ideone.com/nWKeJY UPDATE: Как оказалось, использовать using-as в следующем коде несколько неправильно и его следует заменить на try-finally. using System; public class Test { public static void Main() { var items = new int[] {1, 2, 3, 4, 5, 6, 7}; var enumerator = items.GetEnumerator(); using (enumerator as IDisposable) { var exists = enumerator.MoveNext(); if (exists) { do { var item = enumerator.Current; exists = enumerator.MoveNext(); Console.WriteLine(exists ? "{0}" : "{0} is the last one", item); } while (exists); } } } }
Комментариев нет:
Отправить комментарий