1
0
Эх сурвалжийг харах

Implement Average overloads with selector.

Bart De Smet 7 жил өмнө
parent
commit
568e78fee4

+ 40 - 40
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Average.Generated.cs

@@ -33,7 +33,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<double> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int> selector, CancellationToken cancellationToken)
@@ -43,7 +43,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
         public static Task<double> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<int>> selector)
@@ -53,7 +53,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<double> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<int>> selector, CancellationToken cancellationToken)
@@ -63,7 +63,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
         public static Task<double> AverageAsync(this IAsyncEnumerable<long> source)
@@ -89,7 +89,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<double> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long> selector, CancellationToken cancellationToken)
@@ -99,7 +99,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
         public static Task<double> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<long>> selector)
@@ -109,7 +109,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<double> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<long>> selector, CancellationToken cancellationToken)
@@ -119,7 +119,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
         public static Task<float> AverageAsync(this IAsyncEnumerable<float> source)
@@ -145,7 +145,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<float> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float> selector, CancellationToken cancellationToken)
@@ -155,7 +155,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
         public static Task<float> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<float>> selector)
@@ -165,7 +165,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<float> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<float>> selector, CancellationToken cancellationToken)
@@ -175,7 +175,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
         public static Task<double> AverageAsync(this IAsyncEnumerable<double> source)
@@ -201,7 +201,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<double> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double> selector, CancellationToken cancellationToken)
@@ -211,7 +211,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
         public static Task<double> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<double>> selector)
@@ -221,7 +221,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<double> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<double>> selector, CancellationToken cancellationToken)
@@ -231,7 +231,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
         public static Task<decimal> AverageAsync(this IAsyncEnumerable<decimal> source)
@@ -257,7 +257,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<decimal> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal> selector, CancellationToken cancellationToken)
@@ -267,7 +267,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
         public static Task<decimal> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<decimal>> selector)
@@ -277,7 +277,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<decimal> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<decimal>> selector, CancellationToken cancellationToken)
@@ -287,7 +287,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
         public static Task<double?> AverageAsync(this IAsyncEnumerable<int?> source)
@@ -313,7 +313,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<double?> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int?> selector, CancellationToken cancellationToken)
@@ -323,7 +323,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
         public static Task<double?> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<int?>> selector)
@@ -333,7 +333,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<double?> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<int?>> selector, CancellationToken cancellationToken)
@@ -343,7 +343,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
         public static Task<double?> AverageAsync(this IAsyncEnumerable<long?> source)
@@ -369,7 +369,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<double?> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, long?> selector, CancellationToken cancellationToken)
@@ -379,7 +379,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
         public static Task<double?> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<long?>> selector)
@@ -389,7 +389,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<double?> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<long?>> selector, CancellationToken cancellationToken)
@@ -399,7 +399,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
         public static Task<float?> AverageAsync(this IAsyncEnumerable<float?> source)
@@ -425,7 +425,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<float?> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, float?> selector, CancellationToken cancellationToken)
@@ -435,7 +435,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
         public static Task<float?> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<float?>> selector)
@@ -445,7 +445,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<float?> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<float?>> selector, CancellationToken cancellationToken)
@@ -455,7 +455,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
         public static Task<double?> AverageAsync(this IAsyncEnumerable<double?> source)
@@ -481,7 +481,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<double?> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, double?> selector, CancellationToken cancellationToken)
@@ -491,7 +491,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
         public static Task<double?> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<double?>> selector)
@@ -501,7 +501,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<double?> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<double?>> selector, CancellationToken cancellationToken)
@@ -511,7 +511,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
         public static Task<decimal?> AverageAsync(this IAsyncEnumerable<decimal?> source)
@@ -537,7 +537,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<decimal?> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, decimal?> selector, CancellationToken cancellationToken)
@@ -547,7 +547,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
         public static Task<decimal?> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<decimal?>> selector)
@@ -557,7 +557,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<decimal?> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<decimal?>> selector, CancellationToken cancellationToken)
@@ -567,7 +567,7 @@ namespace System.Linq
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
     }

+ 4 - 4
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Average.Generated.tt

@@ -58,7 +58,7 @@ foreach (var o in os)
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<<#=o.res#>> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, <#=o.type#>> selector, CancellationToken cancellationToken)
@@ -68,7 +68,7 @@ foreach (var o in os)
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
         public static Task<<#=o.res#>> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<<#=o.type#>>> selector)
@@ -78,7 +78,7 @@ foreach (var o in os)
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(CancellationToken.None);
+            return AverageCore(source, selector, CancellationToken.None);
         }
 
         public static Task<<#=o.res#>> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<<#=o.type#>>> selector, CancellationToken cancellationToken)
@@ -88,7 +88,7 @@ foreach (var o in os)
             if (selector == null)
                 throw Error.ArgumentNull(nameof(selector));
 
-            return source.Select(selector).AverageAsync(cancellationToken);
+            return AverageCore(source, selector, cancellationToken);
         }
 
 <#

+ 706 - 44
Ix.NET/Source/System.Linq.Async/System/Linq/Operators/Average.cs

@@ -40,6 +40,66 @@ namespace System.Linq
             }
         }
 
+        private static async Task<double> AverageCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, int> selector, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                if (!await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    throw Error.NoElements();
+                }
+
+                long sum = selector(e.Current);
+                long count = 1;
+                checked
+                {
+                    while (await e.MoveNextAsync().ConfigureAwait(false))
+                    {
+                        sum += selector(e.Current);
+                        ++count;
+                    }
+                }
+
+                return (double)sum / count;
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+        }
+
+        private static async Task<double> AverageCore<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<int>> selector, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                if (!await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    throw Error.NoElements();
+                }
+
+                long sum = await selector(e.Current).ConfigureAwait(false);
+                long count = 1;
+                checked
+                {
+                    while (await e.MoveNextAsync().ConfigureAwait(false))
+                    {
+                        sum += await selector(e.Current).ConfigureAwait(false);
+                        ++count;
+                    }
+                }
+
+                return (double)sum / count;
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+        }
+
         private static async Task<double?> AverageCore(IAsyncEnumerable<int?> source, CancellationToken cancellationToken)
         {
             var e = source.GetAsyncEnumerator(cancellationToken);
@@ -51,7 +111,415 @@ namespace System.Linq
                     var v = e.Current;
                     if (v.HasValue)
                     {
-                        long sum = v.GetValueOrDefault();
+                        long sum = v.GetValueOrDefault();
+                        long count = 1;
+                        checked
+                        {
+                            while (await e.MoveNextAsync().ConfigureAwait(false))
+                            {
+                                v = e.Current;
+                                if (v.HasValue)
+                                {
+                                    sum += v.GetValueOrDefault();
+                                    ++count;
+                                }
+                            }
+                        }
+
+                        return (double)sum / count;
+                    }
+                }
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+
+            return null;
+        }
+
+        private static async Task<double?> AverageCore<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, int?> selector, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                while (await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    var v = selector(e.Current);
+                    if (v.HasValue)
+                    {
+                        long sum = v.GetValueOrDefault();
+                        long count = 1;
+                        checked
+                        {
+                            while (await e.MoveNextAsync().ConfigureAwait(false))
+                            {
+                                v = selector(e.Current);
+                                if (v.HasValue)
+                                {
+                                    sum += v.GetValueOrDefault();
+                                    ++count;
+                                }
+                            }
+                        }
+
+                        return (double)sum / count;
+                    }
+                }
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+
+            return null;
+        }
+
+        private static async Task<double?> AverageCore<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<int?>> selector, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                while (await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    var v = await selector(e.Current).ConfigureAwait(false);
+                    if (v.HasValue)
+                    {
+                        long sum = v.GetValueOrDefault();
+                        long count = 1;
+                        checked
+                        {
+                            while (await e.MoveNextAsync().ConfigureAwait(false))
+                            {
+                                v = await selector(e.Current).ConfigureAwait(false);
+                                if (v.HasValue)
+                                {
+                                    sum += v.GetValueOrDefault();
+                                    ++count;
+                                }
+                            }
+                        }
+
+                        return (double)sum / count;
+                    }
+                }
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+
+            return null;
+        }
+
+        private static async Task<double> AverageCore(IAsyncEnumerable<long> source, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                if (!await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    throw Error.NoElements();
+                }
+
+                var sum = e.Current;
+                long count = 1;
+                checked
+                {
+                    while (await e.MoveNextAsync().ConfigureAwait(false))
+                    {
+                        sum += e.Current;
+                        ++count;
+                    }
+                }
+
+                return (double)sum / count;
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+        }
+
+        private static async Task<double> AverageCore<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, long> selector, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                if (!await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    throw Error.NoElements();
+                }
+
+                var sum = selector(e.Current);
+                long count = 1;
+                checked
+                {
+                    while (await e.MoveNextAsync().ConfigureAwait(false))
+                    {
+                        sum += selector(e.Current);
+                        ++count;
+                    }
+                }
+
+                return (double)sum / count;
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+        }
+
+        private static async Task<double> AverageCore<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<long>> selector, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                if (!await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    throw Error.NoElements();
+                }
+
+                var sum = await selector(e.Current).ConfigureAwait(false);
+                long count = 1;
+                checked
+                {
+                    while (await e.MoveNextAsync().ConfigureAwait(false))
+                    {
+                        sum += await selector(e.Current).ConfigureAwait(false);
+                        ++count;
+                    }
+                }
+
+                return (double)sum / count;
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+        }
+
+        private static async Task<double?> AverageCore(IAsyncEnumerable<long?> source, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                while (await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    var v = e.Current;
+                    if (v.HasValue)
+                    {
+                        var sum = v.GetValueOrDefault();
+                        long count = 1;
+                        checked
+                        {
+                            while (await e.MoveNextAsync().ConfigureAwait(false))
+                            {
+                                v = e.Current;
+                                if (v.HasValue)
+                                {
+                                    sum += v.GetValueOrDefault();
+                                    ++count;
+                                }
+                            }
+                        }
+
+                        return (double)sum / count;
+                    }
+                }
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+
+            return null;
+        }
+
+        private static async Task<double?> AverageCore<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, long?> selector, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                while (await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    var v = selector(e.Current);
+                    if (v.HasValue)
+                    {
+                        var sum = v.GetValueOrDefault();
+                        long count = 1;
+                        checked
+                        {
+                            while (await e.MoveNextAsync().ConfigureAwait(false))
+                            {
+                                v = selector(e.Current);
+                                if (v.HasValue)
+                                {
+                                    sum += v.GetValueOrDefault();
+                                    ++count;
+                                }
+                            }
+                        }
+
+                        return (double)sum / count;
+                    }
+                }
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+
+            return null;
+        }
+
+        private static async Task<double?> AverageCore<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<long?>> selector, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                while (await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    var v = await selector(e.Current).ConfigureAwait(false);
+                    if (v.HasValue)
+                    {
+                        var sum = v.GetValueOrDefault();
+                        long count = 1;
+                        checked
+                        {
+                            while (await e.MoveNextAsync().ConfigureAwait(false))
+                            {
+                                v = await selector(e.Current).ConfigureAwait(false);
+                                if (v.HasValue)
+                                {
+                                    sum += v.GetValueOrDefault();
+                                    ++count;
+                                }
+                            }
+                        }
+
+                        return (double)sum / count;
+                    }
+                }
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+
+            return null;
+        }
+
+        private static async Task<double> AverageCore(IAsyncEnumerable<double> source, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                if (!await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    throw Error.NoElements();
+                }
+
+                var sum = e.Current;
+                long count = 1;
+                while (await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    // There is an opportunity to short-circuit here, in that if e.Current is
+                    // ever NaN then the result will always be NaN. Assuming that this case is
+                    // rare enough that not checking is the better approach generally.
+                    sum += e.Current;
+                    ++count;
+                }
+
+                return sum / count;
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+        }
+
+        private static async Task<double> AverageCore<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, double> selector, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                if (!await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    throw Error.NoElements();
+                }
+
+                var sum = selector(e.Current);
+                long count = 1;
+                while (await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    // There is an opportunity to short-circuit here, in that if e.Current is
+                    // ever NaN then the result will always be NaN. Assuming that this case is
+                    // rare enough that not checking is the better approach generally.
+                    sum += selector(e.Current);
+                    ++count;
+                }
+
+                return sum / count;
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+        }
+
+        private static async Task<double> AverageCore<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<double>> selector, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                if (!await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    throw Error.NoElements();
+                }
+
+                var sum = await selector(e.Current).ConfigureAwait(false);
+                long count = 1;
+                while (await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    // There is an opportunity to short-circuit here, in that if e.Current is
+                    // ever NaN then the result will always be NaN. Assuming that this case is
+                    // rare enough that not checking is the better approach generally.
+                    sum += await selector(e.Current).ConfigureAwait(false);
+                    ++count;
+                }
+
+                return sum / count;
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+        }
+
+        private static async Task<double?> AverageCore(IAsyncEnumerable<double?> source, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                while (await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    var v = e.Current;
+                    if (v.HasValue)
+                    {
+                        var sum = v.GetValueOrDefault();
                         long count = 1;
                         checked
                         {
@@ -66,7 +534,7 @@ namespace System.Linq
                             }
                         }
 
-                        return (double)sum / count;
+                        return sum / count;
                     }
                 }
             }
@@ -78,37 +546,45 @@ namespace System.Linq
             return null;
         }
 
-        private static async Task<double> AverageCore(IAsyncEnumerable<long> source, CancellationToken cancellationToken)
+        private static async Task<double?> AverageCore<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, double?> selector, CancellationToken cancellationToken)
         {
             var e = source.GetAsyncEnumerator(cancellationToken);
 
             try
             {
-                if (!await e.MoveNextAsync().ConfigureAwait(false))
-                {
-                    throw Error.NoElements();
-                }
-
-                var sum = e.Current;
-                long count = 1;
-                checked
+                while (await e.MoveNextAsync().ConfigureAwait(false))
                 {
-                    while (await e.MoveNextAsync().ConfigureAwait(false))
+                    var v = selector(e.Current);
+                    if (v.HasValue)
                     {
-                        sum += e.Current;
-                        ++count;
+                        var sum = v.GetValueOrDefault();
+                        long count = 1;
+                        checked
+                        {
+                            while (await e.MoveNextAsync().ConfigureAwait(false))
+                            {
+                                v = selector(e.Current);
+                                if (v.HasValue)
+                                {
+                                    sum += v.GetValueOrDefault();
+                                    ++count;
+                                }
+                            }
+                        }
+
+                        return sum / count;
                     }
                 }
-
-                return (double)sum / count;
             }
             finally
             {
                 await e.DisposeAsync().ConfigureAwait(false);
             }
+
+            return null;
         }
 
-        private static async Task<double?> AverageCore(IAsyncEnumerable<long?> source, CancellationToken cancellationToken)
+        private static async Task<double?> AverageCore<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<double?>> selector, CancellationToken cancellationToken)
         {
             var e = source.GetAsyncEnumerator(cancellationToken);
 
@@ -116,7 +592,7 @@ namespace System.Linq
             {
                 while (await e.MoveNextAsync().ConfigureAwait(false))
                 {
-                    var v = e.Current;
+                    var v = await selector(e.Current).ConfigureAwait(false);
                     if (v.HasValue)
                     {
                         var sum = v.GetValueOrDefault();
@@ -125,7 +601,7 @@ namespace System.Linq
                         {
                             while (await e.MoveNextAsync().ConfigureAwait(false))
                             {
-                                v = e.Current;
+                                v = await selector(e.Current).ConfigureAwait(false);
                                 if (v.HasValue)
                                 {
                                     sum += v.GetValueOrDefault();
@@ -134,7 +610,7 @@ namespace System.Linq
                             }
                         }
 
-                        return (double)sum / count;
+                        return sum / count;
                     }
                 }
             }
@@ -146,7 +622,7 @@ namespace System.Linq
             return null;
         }
 
-        private static async Task<double> AverageCore(IAsyncEnumerable<double> source, CancellationToken cancellationToken)
+        private static async Task<float> AverageCore(IAsyncEnumerable<float> source, CancellationToken cancellationToken)
         {
             var e = source.GetAsyncEnumerator(cancellationToken);
 
@@ -157,18 +633,15 @@ namespace System.Linq
                     throw Error.NoElements();
                 }
 
-                var sum = e.Current;
+                double sum = e.Current;
                 long count = 1;
                 while (await e.MoveNextAsync().ConfigureAwait(false))
                 {
-                    // There is an opportunity to short-circuit here, in that if e.Current is
-                    // ever NaN then the result will always be NaN. Assuming that this case is
-                    // rare enough that not checking is the better approach generally.
                     sum += e.Current;
                     ++count;
                 }
 
-                return sum / count;
+                return (float)(sum / count);
             }
             finally
             {
@@ -176,7 +649,61 @@ namespace System.Linq
             }
         }
 
-        private static async Task<double?> AverageCore(IAsyncEnumerable<double?> source, CancellationToken cancellationToken)
+        private static async Task<float> AverageCore<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, float> selector, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                if (!await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    throw Error.NoElements();
+                }
+
+                double sum = selector(e.Current);
+                long count = 1;
+                while (await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    sum += selector(e.Current);
+                    ++count;
+                }
+
+                return (float)(sum / count);
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+        }
+
+        private static async Task<float> AverageCore<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<float>> selector, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                if (!await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    throw Error.NoElements();
+                }
+
+                double sum = await selector(e.Current).ConfigureAwait(false);
+                long count = 1;
+                while (await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    sum += await selector(e.Current).ConfigureAwait(false);
+                    ++count;
+                }
+
+                return (float)(sum / count);
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+        }
+
+        private static async Task<float?> AverageCore(IAsyncEnumerable<float?> source, CancellationToken cancellationToken)
         {
             var e = source.GetAsyncEnumerator(cancellationToken);
 
@@ -187,7 +714,7 @@ namespace System.Linq
                     var v = e.Current;
                     if (v.HasValue)
                     {
-                        var sum = v.GetValueOrDefault();
+                        double sum = v.GetValueOrDefault();
                         long count = 1;
                         checked
                         {
@@ -202,7 +729,7 @@ namespace System.Linq
                             }
                         }
 
-                        return sum / count;
+                        return (float)(sum / count);
                     }
                 }
             }
@@ -214,34 +741,45 @@ namespace System.Linq
             return null;
         }
 
-        private static async Task<float> AverageCore(IAsyncEnumerable<float> source, CancellationToken cancellationToken)
+        private static async Task<float?> AverageCore<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, float?> selector, CancellationToken cancellationToken)
         {
             var e = source.GetAsyncEnumerator(cancellationToken);
 
             try
             {
-                if (!await e.MoveNextAsync().ConfigureAwait(false))
-                {
-                    throw Error.NoElements();
-                }
-
-                double sum = e.Current;
-                long count = 1;
                 while (await e.MoveNextAsync().ConfigureAwait(false))
                 {
-                    sum += e.Current;
-                    ++count;
-                }
+                    var v = selector(e.Current);
+                    if (v.HasValue)
+                    {
+                        double sum = v.GetValueOrDefault();
+                        long count = 1;
+                        checked
+                        {
+                            while (await e.MoveNextAsync().ConfigureAwait(false))
+                            {
+                                v = selector(e.Current);
+                                if (v.HasValue)
+                                {
+                                    sum += v.GetValueOrDefault();
+                                    ++count;
+                                }
+                            }
+                        }
 
-                return (float)(sum / count);
+                        return (float)(sum / count);
+                    }
+                }
             }
             finally
             {
                 await e.DisposeAsync().ConfigureAwait(false);
             }
+
+            return null;
         }
 
-        private static async Task<float?> AverageCore(IAsyncEnumerable<float?> source, CancellationToken cancellationToken)
+        private static async Task<float?> AverageCore<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<float?>> selector, CancellationToken cancellationToken)
         {
             var e = source.GetAsyncEnumerator(cancellationToken);
 
@@ -249,7 +787,7 @@ namespace System.Linq
             {
                 while (await e.MoveNextAsync().ConfigureAwait(false))
                 {
-                    var v = e.Current;
+                    var v = await selector(e.Current).ConfigureAwait(false);
                     if (v.HasValue)
                     {
                         double sum = v.GetValueOrDefault();
@@ -258,7 +796,7 @@ namespace System.Linq
                         {
                             while (await e.MoveNextAsync().ConfigureAwait(false))
                             {
-                                v = e.Current;
+                                v = await selector(e.Current).ConfigureAwait(false);
                                 if (v.HasValue)
                                 {
                                     sum += v.GetValueOrDefault();
@@ -306,6 +844,60 @@ namespace System.Linq
             }
         }
 
+        private static async Task<decimal> AverageCore<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, decimal> selector, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                if (!await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    throw Error.NoElements();
+                }
+
+                var sum = selector(e.Current);
+                long count = 1;
+                while (await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    sum += selector(e.Current);
+                    ++count;
+                }
+
+                return sum / count;
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+        }
+
+        private static async Task<decimal> AverageCore<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<decimal>> selector, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                if (!await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    throw Error.NoElements();
+                }
+
+                var sum = await selector(e.Current).ConfigureAwait(false);
+                long count = 1;
+                while (await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    sum += await selector(e.Current).ConfigureAwait(false);
+                    ++count;
+                }
+
+                return sum / count;
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+        }
+
         private static async Task<decimal?> AverageCore(IAsyncEnumerable<decimal?> source, CancellationToken cancellationToken)
         {
             var e = source.GetAsyncEnumerator(cancellationToken);
@@ -340,5 +932,75 @@ namespace System.Linq
 
             return null;
         }
+
+        private static async Task<decimal?> AverageCore<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, decimal?> selector, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                while (await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    var v = selector(e.Current);
+                    if (v.HasValue)
+                    {
+                        var sum = v.GetValueOrDefault();
+                        long count = 1;
+                        while (await e.MoveNextAsync().ConfigureAwait(false))
+                        {
+                            v = selector(e.Current);
+                            if (v.HasValue)
+                            {
+                                sum += v.GetValueOrDefault();
+                                ++count;
+                            }
+                        }
+
+                        return sum / count;
+                    }
+                }
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+
+            return null;
+        }
+
+        private static async Task<decimal?> AverageCore<TSource>(IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<decimal?>> selector, CancellationToken cancellationToken)
+        {
+            var e = source.GetAsyncEnumerator(cancellationToken);
+
+            try
+            {
+                while (await e.MoveNextAsync().ConfigureAwait(false))
+                {
+                    var v = await selector(e.Current).ConfigureAwait(false);
+                    if (v.HasValue)
+                    {
+                        var sum = v.GetValueOrDefault();
+                        long count = 1;
+                        while (await e.MoveNextAsync().ConfigureAwait(false))
+                        {
+                            v = await selector(e.Current).ConfigureAwait(false);
+                            if (v.HasValue)
+                            {
+                                sum += v.GetValueOrDefault();
+                                ++count;
+                            }
+                        }
+
+                        return sum / count;
+                    }
+                }
+            }
+            finally
+            {
+                await e.DisposeAsync().ConfigureAwait(false);
+            }
+
+            return null;
+        }
     }
 }