Иногда вам не хватает роскоши индексирования, или, возможно, вы хотите отменить результаты запроса Linq, или, возможно, вы не хотите изменять исходную коллекцию, если какой-либо из них верен, Linq может помочь вы.
Метод расширения Linq, использующий анонимные типы с Linq Select для предоставления ключа сортировки для Linq OrderByDescending;
public static IEnumerable<T> Invert<T>(this IEnumerable<T> source)
{
var transform = source.Select(
(o, i) => new
{
Index = i,
Object = o
});
return transform.OrderByDescending(o => o.Index)
.Select(o => o.Object);
}
Использование:
var eable = new[]{ "a", "b", "c" };
foreach(var o in eable.Invert())
{
Console.WriteLine(o);
}
// "c", "b", "a"
Он называется «Invert», потому что он синонимичен с «Reverse» и разрешает устранение неоднозначности с реализацией List Reverse.
Можно также изменить некоторые диапазоны коллекции, так как Int32.MinValue и Int32.MaxValue находятся вне диапазона любого вида индекса коллекции, мы можем использовать их для процесса заказа; если индекс элемента ниже заданного диапазона, ему присваивается Int32.MaxValue, чтобы его порядок не изменялся при использовании OrderByDescending, аналогично, элементам с индексом, превышающим заданный диапазон, будет назначаться Int32.MinValue, чтобы они появиться в конце процесса заказа. Всем элементам в данном диапазоне назначается их нормальный индекс, и они соответственно меняются местами.
public static IEnumerable<T> Invert<T>(this IEnumerable<T> source, int index, int count)
{
var transform = source.Select(
(o, i) => new
{
Index = i < index ? Int32.MaxValue : i >= index + count ? Int32.MinValue : i,
Object = o
});
return transform.OrderByDescending(o => o.Index)
.Select(o => o.Object);
}
Использование:
var eable = new[]{ "a", "b", "c", "d" };
foreach(var o in eable.Invert(1, 2))
{
Console.WriteLine(o);
}
// "a", "c", "b", "d"
Я не уверен в падениях производительности этих реализаций Linq по сравнению с использованием временного List для переноса коллекции для реверсирования.
На момент написания статьи я не знал о собственной реализации Reverse в Linq, но все же было весело работать с этим.
https://msdn.microsoft.com/en-us/library/vstudio/bb358497(v=vs.100).aspx