|
using System;
using System.Collections;
using System.Collections.Generic;
namespace Microsoft.Maui
{
internal static class EnumerableExtensions
{
/// <summary>
/// Loops trough each item in <paramref name="enumeration"/> and invokes <paramref name="action"/> on it.
/// </summary>
/// <typeparam name="T">The type of object contained in this collection.</typeparam>
/// <param name="enumeration">The collection to loop through.</param>
/// <param name="action">The action that is invoked on each item in this collection separately.
/// The current item of type <typeparamref name="T"/> will be provided as an input parameter.</param>
public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
foreach (T item in enumeration)
{
action(item);
}
}
/// <summary>
/// Groups elements from an IEnumerable based on a specified key selector function and returns a dictionary
/// where keys are the computed keys and values are lists of elements with the same key.
/// Used by XAML Hot Reload.
/// </summary>
/// <typeparam name="TSource">The type of elements in the input enumeration.</typeparam>
/// <typeparam name="TKey">The type of keys produced by the key selector function.</typeparam>
/// <param name="enumeration">The input IEnumerable of elements to be grouped.</param>
/// <param name="func">A function that extracts a key from an element of the input enumeration.</param>
/// <returns>A dictionary with keys as computed by the key selector function and values as lists of elements
/// that share the same key.</returns>
[Obsolete("Legacy API used in previous versions of XAML Hot Reload. Do not use.")]
public static IDictionary<TKey, List<TSource>> GroupToDictionary<TSource, TKey>(this IEnumerable<TSource> enumeration, Func<TSource, TKey> func)
where TKey : notnull
{
var result = new Dictionary<TKey, List<TSource>>();
foreach (TSource item in enumeration)
{
var group = func(item);
if (!result.TryGetValue(group, out List<TSource>? value))
{
result.Add(group, new List<TSource> { item });
}
else
{
value.Add(item);
}
}
return result;
}
/// <summary>
/// Find the index of a specific item within the collection.
/// </summary>
/// <typeparam name="T">The type of object contained in this collection.</typeparam>
/// <param name="enumerable">The collection in which to look for <paramref name="item"/>.</param>
/// <param name="item">The object to be located in this collection.</param>
/// <returns>The index of <paramref name="item"/> in the collection or -1 when the item is not found.</returns>
/// <exception cref="ArgumentNullException">Throws when <paramref name="enumerable"/> is <see langword="null"/>.</exception>
public static int IndexOf<T>(this IEnumerable<T> enumerable, T item)
{
if (enumerable == null)
{
throw new ArgumentNullException(nameof(enumerable));
}
if (enumerable is IList<T> list)
{
return list.IndexOf(item);
}
if (enumerable is T[] array)
{
return Array.IndexOf(array, item);
}
var i = 0;
foreach (T element in enumerable)
{
if (Equals(element, item))
{
return i;
}
i++;
}
return -1;
}
/// <summary>
/// Find the index of a specific item within the collection.
/// </summary>
/// <param name="enumerable">The collection in which to look for <paramref name="item"/>.</param>
/// <param name="item">The object to be located in this collection.</param>
/// <returns>The index of <paramref name="item"/> in the collection or -1 when the item is not found.</returns>
/// <exception cref="ArgumentNullException">Throws when <paramref name="enumerable"/> is <see langword="null"/>.</exception>
public static int IndexOf(this IEnumerable enumerable, object item)
{
if (enumerable == null)
{
throw new ArgumentNullException(nameof(enumerable));
}
if (enumerable is IList list)
{
return list.IndexOf(item);
}
if (enumerable is Array array)
{
return Array.IndexOf(array, item);
}
var i = 0;
foreach (object element in enumerable)
{
if (Equals(element, item))
{
return i;
}
i++;
}
return -1;
}
/// <summary>
/// Find the index for the first occurrence of an item within the collection as matched through the specified predicate.
/// Used by XAML Hot Reload.
/// </summary>
/// <typeparam name="T">The type of object contained in this collection.</typeparam>
/// <param name="enumerable">The collection in which to look for the item.</param>
/// <param name="predicate">The predicate used to evaluate each item and see if it matches.
/// The item currently evaluated of type <typeparamref name="T"/> is provided as an input parameter.
/// The resulting value should be a <see cref="bool"/> which is <see langword="true"/> if this is the item to match, otherwise <see langword="false"/>.</param>
/// <returns>The index of the first item to match through <paramref name="predicate"/> in the collection or -1 when no match is not found.</returns>
[Obsolete("Use IndexOf<T>(IEnumerable<T>, T item) instead.")]
public static int IndexOf<T>(this IEnumerable<T> enumerable, Func<T, bool> predicate)
{
if (enumerable == null)
{
throw new ArgumentNullException(nameof(enumerable));
}
if (enumerable is List<T> list)
{
var listPredicate = new Predicate<T>(predicate);
return list.FindIndex(listPredicate);
}
if (enumerable is T[] array)
{
var arrayPredicate = new Predicate<T>(predicate);
return Array.FindIndex(array, arrayPredicate);
}
var i = 0;
foreach (T element in enumerable)
{
if (predicate(element))
{
return i;
}
i++;
}
return -1;
}
/// <summary>
/// Retrieves the last item from a <see cref="IList{T}"/> instance.
/// </summary>
/// <typeparam name="T">The type of object to be retrieved from <paramref name="self"/>.</typeparam>
/// <param name="self">The collection to retrieve the last item from.</param>
/// <returns>An object of type <typeparamref name="T"/> that is the last item in the collection.</returns>
public static T Last<T>(this IList<T> self) => self[self.Count - 1];
}
}
|