@@ -2777,7 +2777,7 @@ public string Empty
27772777 get
27782778 {
27792779#if UNITY_AOT
2780- return SR . EmptyEnumerable ;
2780+ return SR . EmptyEnumerable ;
27812781#else
27822782 return Strings . EmptyEnumerable ;
27832783#endif
@@ -2878,5 +2878,117 @@ internal static partial class Error
28782878
28792879 internal static Exception NotSupported ( ) => new NotSupportedException ( ) ;
28802880 }
2881+
2882+ public static partial class Enumerable
2883+ {
2884+ public static IEnumerable < TSource > SkipLast < TSource > ( this IEnumerable < TSource > source , int count )
2885+ {
2886+ if ( source == null )
2887+ {
2888+ throw Error . ArgumentNull ( nameof ( source ) ) ;
2889+ }
2890+
2891+ if ( count <= 0 )
2892+ {
2893+ return source . Skip ( 0 ) ;
2894+ }
2895+
2896+ return SkipLastIterator ( source , count ) ;
2897+ }
2898+
2899+ private static IEnumerable < TSource > SkipLastIterator < TSource > ( IEnumerable < TSource > source , int count )
2900+ {
2901+ var queue = new Queue < TSource > ( ) ;
2902+
2903+ using ( IEnumerator < TSource > e = source . GetEnumerator ( ) )
2904+ {
2905+ while ( e . MoveNext ( ) )
2906+ {
2907+ if ( queue . Count == count )
2908+ {
2909+ do
2910+ {
2911+ yield return queue . Dequeue ( ) ;
2912+ queue . Enqueue ( e . Current ) ;
2913+ }
2914+ while ( e . MoveNext ( ) ) ;
2915+ break ;
2916+ }
2917+ else
2918+ {
2919+ queue . Enqueue ( e . Current ) ;
2920+ }
2921+ }
2922+ }
2923+ }
2924+
2925+ public static IEnumerable < TSource > TakeLast < TSource > ( this IEnumerable < TSource > source , int count )
2926+ {
2927+ if ( source == null )
2928+ {
2929+ throw Error . ArgumentNull ( nameof ( source ) ) ;
2930+ }
2931+
2932+ if ( count <= 0 )
2933+ {
2934+ return EmptyEnumerable < TSource > . Instance ;
2935+ }
2936+
2937+ return TakeLastIterator ( source , count ) ;
2938+ }
2939+
2940+ private static IEnumerable < TSource > TakeLastIterator < TSource > ( IEnumerable < TSource > source , int count )
2941+ {
2942+ Queue < TSource > queue ;
2943+
2944+ using ( IEnumerator < TSource > e = source . GetEnumerator ( ) )
2945+ {
2946+ if ( ! e . MoveNext ( ) )
2947+ {
2948+ yield break ;
2949+ }
2950+
2951+ queue = new Queue < TSource > ( ) ;
2952+ queue . Enqueue ( e . Current ) ;
2953+
2954+ while ( e . MoveNext ( ) )
2955+ {
2956+ if ( queue . Count < count )
2957+ {
2958+ queue . Enqueue ( e . Current ) ;
2959+ }
2960+ else
2961+ {
2962+ do
2963+ {
2964+ queue . Dequeue ( ) ;
2965+ queue . Enqueue ( e . Current ) ;
2966+ }
2967+ while ( e . MoveNext ( ) ) ;
2968+ break ;
2969+ }
2970+ }
2971+ }
2972+
2973+ do
2974+ {
2975+ yield return queue . Dequeue ( ) ;
2976+ }
2977+ while ( queue . Count > 0 ) ;
2978+ }
2979+
2980+ public static HashSet < TSource > ToHashSet < TSource > ( this IEnumerable < TSource > source ) => source . ToHashSet ( comparer : null ) ;
2981+
2982+ public static HashSet < TSource > ToHashSet < TSource > ( this IEnumerable < TSource > source , IEqualityComparer < TSource > comparer )
2983+ {
2984+ if ( source == null )
2985+ {
2986+ throw Error . ArgumentNull ( nameof ( source ) ) ;
2987+ }
2988+
2989+ // Don't pre-allocate based on knowledge of size, as potentially many elements will be dropped.
2990+ return new HashSet < TSource > ( source , comparer ) ;
2991+ }
2992+ }
28812993#endif
28822994}
0 commit comments