Browse Source

Supporting IAsyncPartition in [First|Last|ElementAt][OrDefaut].

Bart De Smet 8 years ago
parent
commit
df9874703a

+ 17 - 2
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ElementAt.cs

@@ -32,10 +32,25 @@ namespace System.Linq
         {
             if (source is IList<TSource> list)
             {
-                return list[index];
+                if (index < list.Count)
+                {
+                    return list[index];
+                }
             }
+            else if (source is IAsyncPartition<TSource> p)
+            {
+                var first = await p.TryGetElementAt(index).ConfigureAwait(false);
 
-            if (index >= 0)
+                if (first.HasValue)
+                {
+                    return first.Value;
+                }
+                else
+                {
+                    throw new ArgumentOutOfRangeException(nameof(index));
+                }
+            }
+            else
             {
                 var e = source.GetAsyncEnumerator();
 

+ 17 - 1
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ElementAtOrDefault.cs

@@ -30,7 +30,23 @@ namespace System.Linq
 
         private static async Task<TSource> ElementAtOrDefaultCore<TSource>(IAsyncEnumerable<TSource> source, int index, CancellationToken cancellationToken)
         {
-            if (index >= 0)
+            if (source is IList<TSource> list)
+            {
+                if (index < list.Count)
+                {
+                    return list[index];
+                }
+            }
+            else if (source is IAsyncPartition<TSource> p)
+            {
+                var first = await p.TryGetElementAt(index).ConfigureAwait(false);
+
+                if (first.HasValue)
+                {
+                    return first.Value;
+                }
+            }
+            else
             {
                 var e = source.GetAsyncEnumerator();
 

+ 24 - 10
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/First.cs

@@ -68,23 +68,37 @@ namespace System.Linq
 
         private static async Task<TSource> FirstCore<TSource>(IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
         {
-            if (source is IList<TSource> list && list.Count > 0)
+            if (source is IList<TSource> list)
             {
-                return list[0];
+                if (list.Count > 0)
+                {
+                    return list[0];
+                }
             }
-
-            var e = source.GetAsyncEnumerator();
-
-            try
+            else if (source is IAsyncPartition<TSource> p)
             {
-                if (await e.MoveNextAsync(cancellationToken).ConfigureAwait(false))
+                var first = await p.TryGetFirst().ConfigureAwait(false);
+
+                if (first.HasValue)
                 {
-                    return e.Current;
+                    return first.Value;
                 }
             }
-            finally
+            else
             {
-                await e.DisposeAsync().ConfigureAwait(false);
+                var e = source.GetAsyncEnumerator();
+
+                try
+                {
+                    if (await e.MoveNextAsync(cancellationToken).ConfigureAwait(false))
+                    {
+                        return e.Current;
+                    }
+                }
+                finally
+                {
+                    await e.DisposeAsync().ConfigureAwait(false);
+                }
             }
 
             throw new InvalidOperationException(Strings.NO_ELEMENTS);

+ 24 - 10
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/FirstOrDefault.cs

@@ -68,23 +68,37 @@ namespace System.Linq
 
         private static async Task<TSource> FirstOrDefaultCore<TSource>(IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
         {
-            if (source is IList<TSource> list && list.Count > 0)
+            if (source is IList<TSource> list)
             {
-                return list[0];
+                if (list.Count > 0)
+                {
+                    return list[0];
+                }
             }
-
-            var e = source.GetAsyncEnumerator();
-
-            try
+            else if (source is IAsyncPartition<TSource> p)
             {
-                if (await e.MoveNextAsync(cancellationToken).ConfigureAwait(false))
+                var first = await p.TryGetFirst().ConfigureAwait(false);
+
+                if (first.HasValue)
                 {
-                    return e.Current;
+                    return first.Value;
                 }
             }
-            finally
+            else
             {
-                await e.DisposeAsync().ConfigureAwait(false);
+                var e = source.GetAsyncEnumerator();
+
+                try
+                {
+                    if (await e.MoveNextAsync(cancellationToken).ConfigureAwait(false))
+                    {
+                        return e.Current;
+                    }
+                }
+                finally
+                {
+                    await e.DisposeAsync().ConfigureAwait(false);
+                }
             }
 
             return default(TSource);

+ 29 - 16
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Last.cs

@@ -68,9 +68,6 @@ namespace System.Linq
 
         private static async Task<TSource> LastCore<TSource>(IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
         {
-            var last = default(TSource);
-            var hasLast = false;
-
             if (source is IList<TSource> list)
             {
                 var count = list.Count;
@@ -79,26 +76,42 @@ namespace System.Linq
                     return list[count - 1];
                 }
             }
-
-            var e = source.GetAsyncEnumerator();
-
-            try
+            else if (source is IAsyncPartition<TSource> p)
             {
-                while (await e.MoveNextAsync(cancellationToken).ConfigureAwait(false))
+                var first = await p.TryGetLast().ConfigureAwait(false);
+
+                if (first.HasValue)
                 {
-                    hasLast = true;
-                    last = e.Current;
+                    return first.Value;
                 }
             }
-            finally
+            else
             {
-                await e.DisposeAsync().ConfigureAwait(false);
-            }
+                var last = default(TSource);
+                var hasLast = false;
+
+                var e = source.GetAsyncEnumerator();
+
+                try
+                {
+                    while (await e.MoveNextAsync(cancellationToken).ConfigureAwait(false))
+                    {
+                        hasLast = true;
+                        last = e.Current;
+                    }
+                }
+                finally
+                {
+                    await e.DisposeAsync().ConfigureAwait(false);
+                }
 
-            if (!hasLast)
-                throw new InvalidOperationException(Strings.NO_ELEMENTS);
+                if (hasLast)
+                {
+                    return last;
+                }
+            }
 
-            return last;
+            throw new InvalidOperationException(Strings.NO_ELEMENTS);
         }
     }
 }

+ 29 - 13
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/LastOrDefault.cs

@@ -68,9 +68,6 @@ namespace System.Linq
 
         private static async Task<TSource> LastOrDefaultCore<TSource>(IAsyncEnumerable<TSource> source, CancellationToken cancellationToken)
         {
-            var last = default(TSource);
-            var hasLast = false;
-
             if (source is IList<TSource> list)
             {
                 var count = list.Count;
@@ -79,23 +76,42 @@ namespace System.Linq
                     return list[count - 1];
                 }
             }
-
-            var e = source.GetAsyncEnumerator();
-
-            try
+            else if (source is IAsyncPartition<TSource> p)
             {
-                while (await e.MoveNextAsync(cancellationToken).ConfigureAwait(false))
+                var first = await p.TryGetLast().ConfigureAwait(false);
+
+                if (first.HasValue)
                 {
-                    hasLast = true;
-                    last = e.Current;
+                    return first.Value;
                 }
             }
-            finally
+            else
             {
-                await e.DisposeAsync().ConfigureAwait(false);
+                var last = default(TSource);
+                var hasLast = false;
+
+                var e = source.GetAsyncEnumerator();
+
+                try
+                {
+                    while (await e.MoveNextAsync(cancellationToken).ConfigureAwait(false))
+                    {
+                        hasLast = true;
+                        last = e.Current;
+                    }
+                }
+                finally
+                {
+                    await e.DisposeAsync().ConfigureAwait(false);
+                }
+
+                if (hasLast)
+                {
+                    return last;
+                }
             }
 
-            return !hasLast ? default(TSource) : last;
+            return default(TSource);
         }
     }
 }