/
OrderBy.cs
157 lines (138 loc) · 9.1 KB
/
OrderBy.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace System.Linq
{
public static partial class Enumerable
{
/// <summary>
/// Sorts the elements of a sequence in ascending order.
/// </summary>
/// <typeparam name="T">The type of the elements of <paramref name="source"/>.</typeparam>
/// <param name="source">A sequence of values to order.</param>
/// <returns>An <see cref="IOrderedEnumerable{TElement}"/> whose elements are sorted.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <remarks>
/// This method is implemented by using deferred execution. The immediate return value is an object
/// that stores all the information that is required to perform the action.
/// The query represented by this method is not executed until the object is enumerated by calling
/// its <see cref="IEnumerable{T}.GetEnumerator"/> method.
///
/// This method compares elements by using the default comparer <see cref="Comparer{T}.Default"/>.
/// </remarks>
public static IOrderedEnumerable<T> Order<T>(this IEnumerable<T> source) =>
Order(source, comparer: null);
/// <summary>
/// Sorts the elements of a sequence in ascending order.
/// </summary>
/// <typeparam name="T">The type of the elements of <paramref name="source"/>.</typeparam>
/// <param name="source">A sequence of values to order.</param>
/// <param name="comparer">An <see cref="IComparer{T}"/> to compare keys.</param>
/// <returns>An <see cref="IOrderedEnumerable{TElement}"/> whose elements are sorted.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <remarks>
/// This method is implemented by using deferred execution. The immediate return value is an object
/// that stores all the information that is required to perform the action.
/// The query represented by this method is not executed until the object is enumerated by calling
/// its <see cref="IEnumerable{T}.GetEnumerator"/> method.
///
/// If comparer is <see langword="null"/>, the default comparer <see cref="Comparer{T}.Default"/> is used to compare elements.
/// </remarks>
public static IOrderedEnumerable<T> Order<T>(this IEnumerable<T> source, IComparer<T>? comparer) =>
TypeIsImplicitlyStable<T>() && (comparer is null || comparer == Comparer<T>.Default) ?
new OrderedImplicitlyStableEnumerable<T>(source, descending: false) :
OrderBy(source, EnumerableSorter<T>.IdentityFunc, comparer);
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
=> new OrderedEnumerable<TSource, TKey>(source, keySelector, null, false, null);
public static IOrderedEnumerable<TSource> OrderBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey>? comparer)
=> new OrderedEnumerable<TSource, TKey>(source, keySelector, comparer, false, null);
/// <summary>
/// Sorts the elements of a sequence in descending order.
/// </summary>
/// <typeparam name="T">The type of the elements of <paramref name="source"/>.</typeparam>
/// <param name="source">A sequence of values to order.</param>
/// <returns>An <see cref="IOrderedEnumerable{TElement}"/> whose elements are sorted.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <remarks>
/// This method is implemented by using deferred execution. The immediate return value is an object
/// that stores all the information that is required to perform the action.
/// The query represented by this method is not executed until the object is enumerated by calling
/// its <see cref="IEnumerable{T}.GetEnumerator"/> method.
///
/// This method compares elements by using the default comparer <see cref="Comparer{T}.Default"/>.
/// </remarks>
public static IOrderedEnumerable<T> OrderDescending<T>(this IEnumerable<T> source) =>
OrderDescending(source, comparer: null);
/// <summary>
/// Sorts the elements of a sequence in descending order.
/// </summary>
/// <typeparam name="T">The type of the elements of <paramref name="source"/>.</typeparam>
/// <param name="source">A sequence of values to order.</param>
/// <param name="comparer">An <see cref="IComparer{T}"/> to compare keys.</param>
/// <returns>An <see cref="IOrderedEnumerable{TElement}"/> whose elements are sorted.</returns>
/// <exception cref="ArgumentNullException"><paramref name="source"/> is <see langword="null"/>.</exception>
/// <remarks>
/// This method is implemented by using deferred execution. The immediate return value is an object
/// that stores all the information that is required to perform the action.
/// The query represented by this method is not executed until the object is enumerated by calling
/// its <see cref="IEnumerable{T}.GetEnumerator"/> method.
///
/// If comparer is <see langword="null"/>, the default comparer <see cref="Comparer{T}.Default"/> is used to compare elements.
/// </remarks>
public static IOrderedEnumerable<T> OrderDescending<T>(this IEnumerable<T> source, IComparer<T>? comparer) =>
TypeIsImplicitlyStable<T>() && (comparer is null || comparer == Comparer<T>.Default) ?
new OrderedImplicitlyStableEnumerable<T>(source, descending: true) :
OrderByDescending(source, EnumerableSorter<T>.IdentityFunc, comparer);
public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) =>
new OrderedEnumerable<TSource, TKey>(source, keySelector, null, true, null);
public static IOrderedEnumerable<TSource> OrderByDescending<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey>? comparer) =>
new OrderedEnumerable<TSource, TKey>(source, keySelector, comparer, true, null);
public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
if (source == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
}
return source.CreateOrderedEnumerable(keySelector, null, false);
}
public static IOrderedEnumerable<TSource> ThenBy<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey>? comparer)
{
if (source == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
}
return source.CreateOrderedEnumerable(keySelector, comparer, false);
}
public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
if (source == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
}
return source.CreateOrderedEnumerable(keySelector, null, true);
}
public static IOrderedEnumerable<TSource> ThenByDescending<TSource, TKey>(this IOrderedEnumerable<TSource> source, Func<TSource, TKey> keySelector, IComparer<TKey>? comparer)
{
if (source == null)
{
ThrowHelper.ThrowArgumentNullException(ExceptionArgument.source);
}
return source.CreateOrderedEnumerable(keySelector, comparer, true);
}
/// <summary>Gets whether the results of an unstable sort will be observably the same as a stable sort.</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool TypeIsImplicitlyStable<T>() =>
typeof(T) == typeof(sbyte) || typeof(T) == typeof(byte) ||
typeof(T) == typeof(int) || typeof(T) == typeof(uint) ||
typeof(T) == typeof(short) || typeof(T) == typeof(ushort) ||
typeof(T) == typeof(long) || typeof(T) == typeof(ulong) ||
typeof(T) == typeof(Int128) || typeof(T) == typeof(UInt128) ||
typeof(T) == typeof(nint) || typeof(T) == typeof(nuint) ||
typeof(T) == typeof(bool) || typeof(T) == typeof(char);
}
public interface IOrderedEnumerable<out TElement> : IEnumerable<TElement>
{
IOrderedEnumerable<TElement> CreateOrderedEnumerable<TKey>(Func<TElement, TKey> keySelector, IComparer<TKey>? comparer, bool descending);
}
}