Average.Generated.tt 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. <#@ template debug="false" hostspecific="false" language="C#" #>
  2. <#@ assembly name="System.Core" #>
  3. <#@ import namespace="System.Linq" #>
  4. <#@ import namespace="System.Text" #>
  5. <#@ import namespace="System.Collections.Generic" #>
  6. <#@ output extension=".cs" #>
  7. // Licensed to the .NET Foundation under one or more agreements.
  8. // The .NET Foundation licenses this file to you under the Apache 2.0 License.
  9. // See the LICENSE file in the project root for more information.
  10. using System.Collections.Generic;
  11. using System.Threading;
  12. using System.Threading.Tasks;
  13. namespace System.Linq
  14. {
  15. public static partial class AsyncEnumerable
  16. {
  17. <#
  18. var os = new[]
  19. {
  20. new { type = "int", res = "double", sum = "long" },
  21. new { type = "long", res = "double", sum = "long" },
  22. new { type = "float", res = "float", sum = "double" },
  23. new { type = "double", res = "double", sum = "double" },
  24. new { type = "decimal", res = "decimal", sum = "decimal" },
  25. new { type = "int?", res = "double?", sum = "long" },
  26. new { type = "long?", res = "double?", sum = "long" },
  27. new { type = "float?", res = "float?", sum = "double" },
  28. new { type = "double?", res = "double?", sum = "double" },
  29. new { type = "decimal?", res = "decimal?", sum = "decimal" },
  30. };
  31. foreach (var o in os)
  32. {
  33. var isNullable = o.type.EndsWith("?");
  34. var t = o.type.TrimEnd('?');
  35. string res = "";
  36. if (t == "int" || t == "long")
  37. res = "(double)sum / count";
  38. else if (t == "double" || t == "decimal")
  39. res = "sum / count";
  40. else if (t == "float")
  41. res = "(float)(sum / count)";
  42. #>
  43. public static ValueTask<<#=o.res#>> AverageAsync(this IAsyncEnumerable<<#=o.type#>> source, CancellationToken cancellationToken = default)
  44. {
  45. if (source == null)
  46. throw Error.ArgumentNull(nameof(source));
  47. return Core(source, cancellationToken);
  48. static async ValueTask<<#=o.res#>> Core(IAsyncEnumerable<<#=o.type#>> _source, CancellationToken _cancellationToken)
  49. {
  50. <#
  51. if (isNullable)
  52. {
  53. #>
  54. var e = _source.GetConfiguredAsyncEnumerator(_cancellationToken, false);
  55. try // REVIEW: Can use `await using` if we get pattern bind (HAS_AWAIT_USING_PATTERN_BIND)
  56. {
  57. while (await e.MoveNextAsync())
  58. {
  59. var v = e.Current;
  60. if (v.HasValue)
  61. {
  62. <#=o.sum#> sum = v.GetValueOrDefault();
  63. long count = 1;
  64. checked
  65. {
  66. while (await e.MoveNextAsync())
  67. {
  68. v = e.Current;
  69. if (v.HasValue)
  70. {
  71. sum += v.GetValueOrDefault();
  72. ++count;
  73. }
  74. }
  75. }
  76. return <#=res#>;
  77. }
  78. }
  79. }
  80. finally
  81. {
  82. await e.DisposeAsync();
  83. }
  84. return null;
  85. <#
  86. }
  87. else
  88. {
  89. #>
  90. var e = _source.GetConfiguredAsyncEnumerator(_cancellationToken, false);
  91. try // REVIEW: Can use `await using` if we get pattern bind (HAS_AWAIT_USING_PATTERN_BIND)
  92. {
  93. if (!await e.MoveNextAsync())
  94. {
  95. throw Error.NoElements();
  96. }
  97. <#=o.sum#> sum = e.Current;
  98. long count = 1;
  99. checked
  100. {
  101. while (await e.MoveNextAsync())
  102. {
  103. sum += e.Current;
  104. ++count;
  105. }
  106. }
  107. return <#=res#>;
  108. }
  109. finally
  110. {
  111. await e.DisposeAsync();
  112. }
  113. <#
  114. }
  115. #>
  116. }
  117. }
  118. public static ValueTask<<#=o.res#>> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, <#=o.type#>> selector, CancellationToken cancellationToken = default)
  119. {
  120. if (source == null)
  121. throw Error.ArgumentNull(nameof(source));
  122. if (selector == null)
  123. throw Error.ArgumentNull(nameof(selector));
  124. return Core(source, selector, cancellationToken);
  125. static async ValueTask<<#=o.res#>> Core(IAsyncEnumerable<TSource> _source, Func<TSource, <#=o.type#>> _selector, CancellationToken _cancellationToken)
  126. {
  127. <#
  128. if (isNullable)
  129. {
  130. #>
  131. var e = _source.GetConfiguredAsyncEnumerator(_cancellationToken, false);
  132. try // REVIEW: Can use `await using` if we get pattern bind (HAS_AWAIT_USING_PATTERN_BIND)
  133. {
  134. while (await e.MoveNextAsync())
  135. {
  136. var v = _selector(e.Current);
  137. if (v.HasValue)
  138. {
  139. <#=o.sum#> sum = v.GetValueOrDefault();
  140. long count = 1;
  141. checked
  142. {
  143. while (await e.MoveNextAsync())
  144. {
  145. v = _selector(e.Current);
  146. if (v.HasValue)
  147. {
  148. sum += v.GetValueOrDefault();
  149. ++count;
  150. }
  151. }
  152. }
  153. return <#=res#>;
  154. }
  155. }
  156. }
  157. finally
  158. {
  159. await e.DisposeAsync();
  160. }
  161. return null;
  162. <#
  163. }
  164. else
  165. {
  166. #>
  167. var e = _source.GetConfiguredAsyncEnumerator(_cancellationToken, false);
  168. try // REVIEW: Can use `await using` if we get pattern bind (HAS_AWAIT_USING_PATTERN_BIND)
  169. {
  170. if (!await e.MoveNextAsync())
  171. {
  172. throw Error.NoElements();
  173. }
  174. <#=o.sum#> sum = _selector(e.Current);
  175. long count = 1;
  176. checked
  177. {
  178. while (await e.MoveNextAsync())
  179. {
  180. sum += _selector(e.Current);
  181. ++count;
  182. }
  183. }
  184. return <#=res#>;
  185. }
  186. finally
  187. {
  188. await e.DisposeAsync();
  189. }
  190. <#
  191. }
  192. #>
  193. }
  194. }
  195. public static ValueTask<<#=o.res#>> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<<#=o.type#>>> selector, CancellationToken cancellationToken = default)
  196. {
  197. if (source == null)
  198. throw Error.ArgumentNull(nameof(source));
  199. if (selector == null)
  200. throw Error.ArgumentNull(nameof(selector));
  201. return Core(source, selector, cancellationToken);
  202. static async ValueTask<<#=o.res#>> Core(IAsyncEnumerable<TSource> _source, Func<TSource, ValueTask<<#=o.type#>>> _selector, CancellationToken _cancellationToken)
  203. {
  204. <#
  205. if (isNullable)
  206. {
  207. #>
  208. var e = _source.GetConfiguredAsyncEnumerator(_cancellationToken, false);
  209. try // REVIEW: Can use `await using` if we get pattern bind (HAS_AWAIT_USING_PATTERN_BIND)
  210. {
  211. while (await e.MoveNextAsync())
  212. {
  213. var v = await _selector(e.Current).ConfigureAwait(false);
  214. if (v.HasValue)
  215. {
  216. <#=o.sum#> sum = v.GetValueOrDefault();
  217. long count = 1;
  218. checked
  219. {
  220. while (await e.MoveNextAsync())
  221. {
  222. v = await _selector(e.Current).ConfigureAwait(false);
  223. if (v.HasValue)
  224. {
  225. sum += v.GetValueOrDefault();
  226. ++count;
  227. }
  228. }
  229. }
  230. return <#=res#>;
  231. }
  232. }
  233. }
  234. finally
  235. {
  236. await e.DisposeAsync();
  237. }
  238. return null;
  239. <#
  240. }
  241. else
  242. {
  243. #>
  244. var e = _source.GetConfiguredAsyncEnumerator(_cancellationToken, false);
  245. try // REVIEW: Can use `await using` if we get pattern bind (HAS_AWAIT_USING_PATTERN_BIND)
  246. {
  247. if (!await e.MoveNextAsync())
  248. {
  249. throw Error.NoElements();
  250. }
  251. <#=o.sum#> sum = await _selector(e.Current).ConfigureAwait(false);
  252. long count = 1;
  253. checked
  254. {
  255. while (await e.MoveNextAsync())
  256. {
  257. sum += await _selector(e.Current).ConfigureAwait(false);
  258. ++count;
  259. }
  260. }
  261. return <#=res#>;
  262. }
  263. finally
  264. {
  265. await e.DisposeAsync();
  266. }
  267. <#
  268. }
  269. #>
  270. }
  271. }
  272. #if !NO_DEEP_CANCELLATION
  273. public static ValueTask<<#=o.res#>> AverageAsync<TSource>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<<#=o.type#>>> selector, CancellationToken cancellationToken = default)
  274. {
  275. if (source == null)
  276. throw Error.ArgumentNull(nameof(source));
  277. if (selector == null)
  278. throw Error.ArgumentNull(nameof(selector));
  279. return Core(source, selector, cancellationToken);
  280. static async ValueTask<<#=o.res#>> Core(IAsyncEnumerable<TSource> _source, Func<TSource, CancellationToken, ValueTask<<#=o.type#>>> _selector, CancellationToken _cancellationToken)
  281. {
  282. <#
  283. if (isNullable)
  284. {
  285. #>
  286. var e = _source.GetConfiguredAsyncEnumerator(_cancellationToken, false);
  287. try // REVIEW: Can use `await using` if we get pattern bind (HAS_AWAIT_USING_PATTERN_BIND)
  288. {
  289. while (await e.MoveNextAsync())
  290. {
  291. var v = await _selector(e.Current, _cancellationToken).ConfigureAwait(false);
  292. if (v.HasValue)
  293. {
  294. <#=o.sum#> sum = v.GetValueOrDefault();
  295. long count = 1;
  296. checked
  297. {
  298. while (await e.MoveNextAsync())
  299. {
  300. v = await _selector(e.Current, _cancellationToken).ConfigureAwait(false);
  301. if (v.HasValue)
  302. {
  303. sum += v.GetValueOrDefault();
  304. ++count;
  305. }
  306. }
  307. }
  308. return <#=res#>;
  309. }
  310. }
  311. }
  312. finally
  313. {
  314. await e.DisposeAsync();
  315. }
  316. return null;
  317. <#
  318. }
  319. else
  320. {
  321. #>
  322. var e = _source.GetConfiguredAsyncEnumerator(_cancellationToken, false);
  323. try // REVIEW: Can use `await using` if we get pattern bind (HAS_AWAIT_USING_PATTERN_BIND)
  324. {
  325. if (!await e.MoveNextAsync())
  326. {
  327. throw Error.NoElements();
  328. }
  329. <#=o.sum#> sum = await _selector(e.Current, _cancellationToken).ConfigureAwait(false);
  330. long count = 1;
  331. checked
  332. {
  333. while (await e.MoveNextAsync())
  334. {
  335. sum += await _selector(e.Current, _cancellationToken).ConfigureAwait(false);
  336. ++count;
  337. }
  338. }
  339. return <#=res#>;
  340. }
  341. finally
  342. {
  343. await e.DisposeAsync();
  344. }
  345. <#
  346. }
  347. #>
  348. }
  349. }
  350. #endif
  351. <#
  352. }
  353. #>
  354. }
  355. }