// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT License. // See the LICENSE file in the project root for more information. using System.Collections.Generic; namespace System.Linq { public static partial class EnumerableEx { /// /// Returns consecutive distinct elements by using the default equality comparer to compare values. /// /// Source sequence element type. /// Source sequence. /// Sequence without adjacent non-distinct elements. public static IEnumerable DistinctUntilChanged(this IEnumerable source) { if (source == null) throw new ArgumentNullException(nameof(source)); return DistinctUntilChangedCore(source, x => x, EqualityComparer.Default); } /// /// Returns consecutive distinct elements by using the specified equality comparer to compare values. /// /// Source sequence element type. /// Source sequence. /// Comparer used to compare values. /// Sequence without adjacent non-distinct elements. public static IEnumerable DistinctUntilChanged(this IEnumerable source, IEqualityComparer comparer) { if (source == null) throw new ArgumentNullException(nameof(source)); if (comparer == null) throw new ArgumentNullException(nameof(comparer)); return DistinctUntilChangedCore(source, x => x, comparer); } /// /// Returns consecutive distinct elements based on a key value by using the specified equality comparer to compare key values. /// /// Source sequence element type. /// Key type. /// Source sequence. /// Key selector. /// Sequence without adjacent non-distinct elements. public static IEnumerable DistinctUntilChanged(this IEnumerable source, Func keySelector) { if (source == null) throw new ArgumentNullException(nameof(source)); if (keySelector == null) throw new ArgumentNullException(nameof(keySelector)); return DistinctUntilChangedCore(source, keySelector, EqualityComparer.Default); } /// /// Returns consecutive distinct elements based on a key value by using the specified equality comparer to compare key values. /// /// Source sequence element type. /// Key type. /// Source sequence. /// Key selector. /// Comparer used to compare key values. /// Sequence without adjacent non-distinct elements. public static IEnumerable DistinctUntilChanged(this IEnumerable source, Func keySelector, IEqualityComparer comparer) { if (source == null) throw new ArgumentNullException(nameof(source)); if (keySelector == null) throw new ArgumentNullException(nameof(keySelector)); if (comparer == null) throw new ArgumentNullException(nameof(comparer)); return DistinctUntilChangedCore(source, keySelector, comparer); } private static IEnumerable DistinctUntilChangedCore(IEnumerable source, Func keySelector, IEqualityComparer comparer) { var currentKey = default(TKey)!; var hasCurrentKey = false; foreach (var item in source) { var key = keySelector(item); var comparerEquals = false; if (hasCurrentKey) { comparerEquals = comparer.Equals(currentKey, key); } if (!hasCurrentKey || !comparerEquals) { hasCurrentKey = true; currentKey = key; yield return item; } } } } }