فهرست منبع

Optimize ToDictionary.

Bart De Smet 7 سال پیش
والد
کامیت
117625f92f
1فایلهای تغییر یافته به همراه67 افزوده شده و 31 حذف شده
  1. 67 31
      Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToDictionary.cs

+ 67 - 31
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/ToDictionary.cs

@@ -17,7 +17,7 @@ namespace System.Linq
             if (keySelector == null)
                 throw new ArgumentNullException(nameof(keySelector));
 
-            return ToDictionary(source, keySelector, CancellationToken.None);
+            return ToDictionaryCore(source, keySelector, x => x, EqualityComparer<TKey>.Default, CancellationToken.None);
         }
 
         public static Task<Dictionary<TKey, TSource>> ToDictionary<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, CancellationToken cancellationToken)
@@ -27,7 +27,7 @@ namespace System.Linq
             if (keySelector == null)
                 throw new ArgumentNullException(nameof(keySelector));
 
-            return source.ToDictionary(keySelector, x => x, EqualityComparer<TKey>.Default, cancellationToken);
+            return ToDictionaryCore(source, keySelector, x => x, EqualityComparer<TKey>.Default, cancellationToken);
         }
 
         public static Task<Dictionary<TKey, TSource>> ToDictionary<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, Task<TKey>> keySelector)
@@ -37,7 +37,7 @@ namespace System.Linq
             if (keySelector == null)
                 throw new ArgumentNullException(nameof(keySelector));
 
-            return ToDictionary(source, keySelector, CancellationToken.None);
+            return ToDictionaryCore(source, keySelector, x => Task.FromResult(x), EqualityComparer<TKey>.Default, CancellationToken.None);
         }
 
         public static Task<Dictionary<TKey, TSource>> ToDictionary<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, Task<TKey>> keySelector, CancellationToken cancellationToken)
@@ -47,7 +47,7 @@ namespace System.Linq
             if (keySelector == null)
                 throw new ArgumentNullException(nameof(keySelector));
 
-            return source.ToDictionary(keySelector, x => Task.FromResult(x), EqualityComparer<TKey>.Default, cancellationToken);
+            return ToDictionaryCore(source, keySelector, x => Task.FromResult(x), EqualityComparer<TKey>.Default, cancellationToken);
         }
 
         public static Task<Dictionary<TKey, TSource>> ToDictionary<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer)
@@ -59,7 +59,7 @@ namespace System.Linq
             if (comparer == null)
                 throw new ArgumentNullException(nameof(comparer));
 
-            return ToDictionary(source, keySelector, comparer, CancellationToken.None);
+            return ToDictionaryCore(source, keySelector, x => x, comparer, CancellationToken.None);
         }
 
         public static Task<Dictionary<TKey, TSource>> ToDictionary<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
@@ -71,7 +71,7 @@ namespace System.Linq
             if (comparer == null)
                 throw new ArgumentNullException(nameof(comparer));
 
-            return source.ToDictionary(keySelector, x => x, comparer, cancellationToken);
+            return ToDictionaryCore(source, keySelector, x => x, comparer, cancellationToken);
         }
 
         public static Task<Dictionary<TKey, TSource>> ToDictionary<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, Task<TKey>> keySelector, IEqualityComparer<TKey> comparer)
@@ -83,7 +83,7 @@ namespace System.Linq
             if (comparer == null)
                 throw new ArgumentNullException(nameof(comparer));
 
-            return ToDictionary(source, keySelector, comparer, CancellationToken.None);
+            return ToDictionaryCore(source, keySelector, x => Task.FromResult(x), comparer, CancellationToken.None);
         }
 
         public static Task<Dictionary<TKey, TSource>> ToDictionary<TSource, TKey>(this IAsyncEnumerable<TSource> source, Func<TSource, Task<TKey>> keySelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
@@ -95,7 +95,7 @@ namespace System.Linq
             if (comparer == null)
                 throw new ArgumentNullException(nameof(comparer));
 
-            return source.ToDictionary(keySelector, x => Task.FromResult(x), comparer, cancellationToken);
+            return ToDictionaryCore(source, keySelector, x => Task.FromResult(x), comparer, cancellationToken);
         }
 
         public static Task<Dictionary<TKey, TElement>> ToDictionary<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector)
@@ -107,7 +107,7 @@ namespace System.Linq
             if (elementSelector == null)
                 throw new ArgumentNullException(nameof(elementSelector));
 
-            return ToDictionary(source, keySelector, elementSelector, CancellationToken.None);
+            return ToDictionaryCore(source, keySelector, elementSelector, EqualityComparer<TKey>.Default, CancellationToken.None);
         }
 
         public static Task<Dictionary<TKey, TElement>> ToDictionary<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, CancellationToken cancellationToken)
@@ -119,7 +119,7 @@ namespace System.Linq
             if (elementSelector == null)
                 throw new ArgumentNullException(nameof(elementSelector));
 
-            return source.ToDictionary(keySelector, elementSelector, EqualityComparer<TKey>.Default, cancellationToken);
+            return ToDictionaryCore(source, keySelector, elementSelector, EqualityComparer<TKey>.Default, cancellationToken);
         }
 
         public static Task<Dictionary<TKey, TElement>> ToDictionary<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, Task<TKey>> keySelector, Func<TSource, Task<TElement>> elementSelector)
@@ -131,7 +131,7 @@ namespace System.Linq
             if (elementSelector == null)
                 throw new ArgumentNullException(nameof(elementSelector));
 
-            return ToDictionary(source, keySelector, elementSelector, CancellationToken.None);
+            return ToDictionaryCore(source, keySelector, elementSelector, EqualityComparer<TKey>.Default, CancellationToken.None);
         }
 
         public static Task<Dictionary<TKey, TElement>> ToDictionary<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, Task<TKey>> keySelector, Func<TSource, Task<TElement>> elementSelector, CancellationToken cancellationToken)
@@ -143,7 +143,7 @@ namespace System.Linq
             if (elementSelector == null)
                 throw new ArgumentNullException(nameof(elementSelector));
 
-            return source.ToDictionary(keySelector, elementSelector, EqualityComparer<TKey>.Default, cancellationToken);
+            return ToDictionaryCore(source, keySelector, elementSelector, EqualityComparer<TKey>.Default, cancellationToken);
         }
 
         public static Task<Dictionary<TKey, TElement>> ToDictionary<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer)
@@ -157,7 +157,7 @@ namespace System.Linq
             if (comparer == null)
                 throw new ArgumentNullException(nameof(comparer));
 
-            return ToDictionary(source, keySelector, elementSelector, comparer, CancellationToken.None);
+            return ToDictionaryCore(source, keySelector, elementSelector, comparer, CancellationToken.None);
         }
 
         public static Task<Dictionary<TKey, TElement>> ToDictionary<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
@@ -171,15 +171,7 @@ namespace System.Linq
             if (comparer == null)
                 throw new ArgumentNullException(nameof(comparer));
 
-            return source.Aggregate(
-                new Dictionary<TKey, TElement>(comparer),
-                (d, x) =>
-                {
-                    d.Add(keySelector(x), elementSelector(x));
-                    return d;
-                },
-                cancellationToken
-            );
+            return ToDictionaryCore(source, keySelector, elementSelector, comparer, cancellationToken);
         }
 
         public static Task<Dictionary<TKey, TElement>> ToDictionary<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, Task<TKey>> keySelector, Func<TSource, Task<TElement>> elementSelector, IEqualityComparer<TKey> comparer)
@@ -193,7 +185,7 @@ namespace System.Linq
             if (comparer == null)
                 throw new ArgumentNullException(nameof(comparer));
 
-            return ToDictionary(source, keySelector, elementSelector, comparer, CancellationToken.None);
+            return ToDictionaryCore(source, keySelector, elementSelector, comparer, CancellationToken.None);
         }
 
         public static Task<Dictionary<TKey, TElement>> ToDictionary<TSource, TKey, TElement>(this IAsyncEnumerable<TSource> source, Func<TSource, Task<TKey>> keySelector, Func<TSource, Task<TElement>> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
@@ -207,15 +199,59 @@ namespace System.Linq
             if (comparer == null)
                 throw new ArgumentNullException(nameof(comparer));
 
-            return source.Aggregate(
-                new Dictionary<TKey, TElement>(comparer),
-                async (d, x) =>
+            return ToDictionaryCore(source, keySelector, elementSelector, comparer, cancellationToken);
+        }
+
+        private static async Task<Dictionary<TKey, TElement>> ToDictionaryCore<TSource, TKey, TElement>(IAsyncEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                var d = new Dictionary<TKey, TElement>(comparer);
+
+                while (await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    var x = e.Current;
+
+                    var key = keySelector(x);
+                    var value = elementSelector(x);
+
+                    d.Add(key, value);
+                }
+
+                return d;
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+        }
+
+        private static async Task<Dictionary<TKey, TElement>> ToDictionaryCore<TSource, TKey, TElement>(IAsyncEnumerable<TSource> source, Func<TSource, Task<TKey>> keySelector, Func<TSource, Task<TElement>> elementSelector, IEqualityComparer<TKey> comparer, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                var d = new Dictionary<TKey, TElement>(comparer);
+
+                while (await e.MoveNextAsync().ConfigureAwait(false))
                 {
-                    d.Add(await keySelector(x).ConfigureAwait(false), await elementSelector(x).ConfigureAwait(false));
-                    return d;
-                },
-                cancellationToken
-            );
+                    var x = e.Current;
+
+                    var key = await keySelector(x).ConfigureAwait(false);
+                    var value = await elementSelector(x).ConfigureAwait(false);
+
+                    d.Add(key, value);
+                }
+
+                return d;
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
         }
     }
 }