/* * Copyright (c) 2025 Proton AG * * This file is part of ProtonVPN. * * ProtonVPN is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * ProtonVPN is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ProtonVPN. If not, see . */ namespace ProtonVPN.Common.Core.Extensions; public static class EnumerableExtensions { // Code forked and edited from System.Linq.Enumerable (First.cs) public static T? FirstOrNull(this IEnumerable source) where T : struct { ArgumentNullException.ThrowIfNull(source, nameof(source)); if (source is IList list) { if (list.Count > 0) { return list[0]; } } else { using (IEnumerator e = source.GetEnumerator()) { if (e.MoveNext()) { return e.Current; } } } return null; } // Code forked and edited from System.Linq.Enumerable (First.cs) public static T? FirstOrNull(this IEnumerable source, Func predicate) where T : struct { ArgumentNullException.ThrowIfNull(source, nameof(source)); ArgumentNullException.ThrowIfNull(predicate, nameof(predicate)); foreach (T element in source) { if (predicate(element)) { return element; } } return null; } /// /// Runs on each element in sequence. /// /// The type of the elements of . /// The to run on. /// An action to run on each element of sequence. public static void ForEach(this IEnumerable source, Action action) { foreach (T? item in source) { action(item); } } /// /// Returns distinct elements from a sequence by using a specified selector to compare values. /// /// The type of elements in a sequence. /// The type of the value returned by the selector to determine unique elements. /// The sequence of source elements. /// A function that selects a value to determine unique elements by. /// An that contains distinct elements from the source sequence. public static IEnumerable Distinct(this IEnumerable source, Func selector) { HashSet set = []; foreach (T? item in source) { TSelected? selectedValue = selector(item); if (set.Add(selectedValue)) { yield return item; } } } }