namespace QWERTYkez.WordProcessor;
internal static class IeExtension
{
///
/// Выполняет указанные действия для первого и последующих элементов последовательности.
///
/// Тип элементов последовательности.
/// Последовательность элементов.
/// Действие над первым элементом (если есть).
/// Действие над каждым последующим элементом, начиная со второго.
/// Возникает, если items или любой из делегатов равен null.
public static void ForFirstNext(this IEnumerable items, Action first, Action next)
{
if (items is null) throw new ArgumentNullException(nameof(items));
if (first is null) throw new ArgumentNullException(nameof(first));
if (next is null) throw new ArgumentNullException(nameof(next));
using var enumerator = items.GetEnumerator();
if (!enumerator.MoveNext())
return;
first(enumerator.Current);
while (enumerator.MoveNext())
{
next(enumerator.Current);
}
}
///
/// Выполняет указанные действия для первого, промежуточных и последнего элементов последовательности.
/// Если последовательность содержит только один элемент, то для него вызываются и first, и last.
///
/// Тип элементов последовательности.
/// Последовательность элементов.
/// Действие над первым элементом.
/// Действие над элементами, которые не являются ни первыми, ни последними.
/// Действие над последним элементом.
/// Возникает, если items или любой из делегатов равен null.
public static void ForFirstNextLast(this IEnumerable items, Action first, Action next, Action last)
{
if (items is null) throw new ArgumentNullException(nameof(items));
if (first is null) throw new ArgumentNullException(nameof(first));
if (next is null) throw new ArgumentNullException(nameof(next));
if (last is null) throw new ArgumentNullException(nameof(last));
using var enumerator = items.GetEnumerator();
if (!enumerator.MoveNext())
return;
T firstItem = enumerator.Current;
// Если только один элемент
if (!enumerator.MoveNext())
{
first(firstItem);
last(firstItem);
return;
}
// Есть как минимум два элемента
first(firstItem);
T prev = enumerator.Current; // второй элемент
while (enumerator.MoveNext())
{
next(prev); // предыдущий элемент точно не последний
prev = enumerator.Current;
}
last(prev); // последний элемент
}
///
/// Выполняет указанные действия для всех элементов, кроме последнего, и для последнего элемента.
/// Если последовательность содержит только один элемент, то вызывается только last.
///
/// Тип элементов последовательности.
/// Последовательность элементов.
/// Действие над элементами, не являющимися последними.
/// Действие над последним элементом.
/// Возникает, если items или любой из делегатов равен null.
public static void ForNextLast(this IEnumerable items, Action next, Action last)
{
if (items is null) throw new ArgumentNullException(nameof(items));
if (next is null) throw new ArgumentNullException(nameof(next));
if (last is null) throw new ArgumentNullException(nameof(last));
using var enumerator = items.GetEnumerator();
if (!enumerator.MoveNext())
return;
T prev = enumerator.Current;
while (enumerator.MoveNext())
{
next(prev);
prev = enumerator.Current;
}
last(prev);
}
}