using System; using System.Collections.Generic; using System.Linq; namespace Semmle.Util { public static class IEnumerableExtensions { /// /// Find the first element in the sequence, or null if the sequence is empty. /// /// The type of the sequence. /// The list of items. /// The first item, or null if the sequence is empty. public static T? FirstOrNull(this IEnumerable list) where T : struct { return list.Any() ? (T?)list.First() : null; } /// /// Finds the last element a sequence, or null if the sequence is empty. /// /// The type of the elements in the sequence. /// The list of items. /// The last item, or null if the sequence is empty. public static T? LastOrNull(this IEnumerable list) where T : struct { return list.Any() ? (T?)list.Last() : null; } /// /// Interleaves the elements from the two sequences. /// public static IEnumerable Interleave(this IEnumerable first, IEnumerable second) { using var enumerator1 = first.GetEnumerator(); using var enumerator2 = second.GetEnumerator(); bool moveNext1; while ((moveNext1 = enumerator1.MoveNext()) && enumerator2.MoveNext()) { yield return enumerator1.Current; yield return enumerator2.Current; } if (moveNext1) { // `first` has more elements than `second` yield return enumerator1.Current; while (enumerator1.MoveNext()) { yield return enumerator1.Current; } } while (enumerator2.MoveNext()) { // `second` has more elements than `first` yield return enumerator2.Current; } } /// /// Enumerates a possibly null enumerable. /// If the enumerable is null, the list is empty. /// public static IEnumerable EnumerateNull(this IEnumerable? items) { if (items == null) yield break; foreach (var item in items) yield return item; } /// /// Applies the action to each item in this collection. /// public static void ForEach(this IEnumerable items, Action a) { foreach (var item in items) a(item); } /// /// Forces enumeration of this collection and discards the result. /// public static void Enumerate(this IEnumerable items) { items.ForEach(_ => { }); } /// /// Computes a hash of a sequence. /// /// The type of the item. /// The list of items to hash. /// The hash code. public static int SequenceHash(this IEnumerable items) where T : notnull { var h = 0; foreach (var i in items) h = h * 7 + i.GetHashCode(); return h; } } }