Max.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the Apache 2.0 License.
  3. // See the LICENSE file in the project root for more information.
  4. using System.Collections.Generic;
  5. using System.Threading;
  6. using System.Threading.Tasks;
  7. namespace System.Linq
  8. {
  9. public static partial class AsyncEnumerable
  10. {
  11. public static Task<TSource> MaxAsync<TSource>(this IAsyncEnumerable<TSource> source, CancellationToken cancellationToken = default)
  12. {
  13. if (source == null)
  14. throw Error.ArgumentNull(nameof(source));
  15. if (default(TSource) == null)
  16. {
  17. return Core(source, cancellationToken);
  18. static async Task<TSource> Core(IAsyncEnumerable<TSource> _source, CancellationToken _cancellationToken)
  19. {
  20. var comparer = Comparer<TSource>.Default;
  21. var value = default(TSource);
  22. #if CSHARP8
  23. await using (var e = _source.GetAsyncEnumerator(_cancellationToken).ConfigureAwait(false))
  24. {
  25. do
  26. {
  27. if (!await e.MoveNextAsync())
  28. {
  29. return value;
  30. }
  31. value = e.Current;
  32. }
  33. while (value == null);
  34. while (await e.MoveNextAsync())
  35. {
  36. var x = e.Current;
  37. if (x != null && comparer.Compare(x, value) > 0)
  38. {
  39. value = x;
  40. }
  41. }
  42. }
  43. #else
  44. var e = _source.GetAsyncEnumerator(_cancellationToken);
  45. try
  46. {
  47. do
  48. {
  49. if (!await e.MoveNextAsync().ConfigureAwait(false))
  50. {
  51. return value;
  52. }
  53. value = e.Current;
  54. }
  55. while (value == null);
  56. while (await e.MoveNextAsync().ConfigureAwait(false))
  57. {
  58. var x = e.Current;
  59. if (x != null && comparer.Compare(x, value) > 0)
  60. {
  61. value = x;
  62. }
  63. }
  64. }
  65. finally
  66. {
  67. await e.DisposeAsync().ConfigureAwait(false);
  68. }
  69. #endif
  70. return value;
  71. }
  72. }
  73. else
  74. {
  75. return Core(source, cancellationToken);
  76. static async Task<TSource> Core(IAsyncEnumerable<TSource> _source, CancellationToken _cancellationToken)
  77. {
  78. var comparer = Comparer<TSource>.Default;
  79. var value = default(TSource);
  80. #if CSHARP8
  81. await using (var e = _source.GetAsyncEnumerator(_cancellationToken).ConfigureAwait(false))
  82. {
  83. if (!await e.MoveNextAsync())
  84. {
  85. throw Error.NoElements();
  86. }
  87. value = e.Current;
  88. while (await e.MoveNextAsync())
  89. {
  90. var x = e.Current;
  91. if (comparer.Compare(x, value) > 0)
  92. {
  93. value = x;
  94. }
  95. }
  96. }
  97. #else
  98. var e = _source.GetAsyncEnumerator(_cancellationToken);
  99. try
  100. {
  101. if (!await e.MoveNextAsync().ConfigureAwait(false))
  102. {
  103. throw Error.NoElements();
  104. }
  105. value = e.Current;
  106. while (await e.MoveNextAsync().ConfigureAwait(false))
  107. {
  108. var x = e.Current;
  109. if (comparer.Compare(x, value) > 0)
  110. {
  111. value = x;
  112. }
  113. }
  114. }
  115. finally
  116. {
  117. await e.DisposeAsync().ConfigureAwait(false);
  118. }
  119. #endif
  120. return value;
  121. }
  122. }
  123. }
  124. public static Task<TResult> MaxAsync<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, TResult> selector, CancellationToken cancellationToken = default)
  125. {
  126. if (source == null)
  127. throw Error.ArgumentNull(nameof(source));
  128. if (selector == null)
  129. throw Error.ArgumentNull(nameof(selector));
  130. if (default(TResult) == null)
  131. {
  132. return Core(source, selector, cancellationToken);
  133. static async Task<TResult> Core(IAsyncEnumerable<TSource> _source, Func<TSource, TResult> _selector, CancellationToken _cancellationToken)
  134. {
  135. var comparer = Comparer<TResult>.Default;
  136. var value = default(TResult);
  137. #if CSHARP8
  138. await using (var e = _source.GetAsyncEnumerator(_cancellationToken).ConfigureAwait(false))
  139. {
  140. do
  141. {
  142. if (!await e.MoveNextAsync())
  143. {
  144. return value;
  145. }
  146. value = _selector(e.Current);
  147. }
  148. while (value == null);
  149. while (await e.MoveNextAsync())
  150. {
  151. var x = _selector(e.Current);
  152. if (x != null && comparer.Compare(x, value) > 0)
  153. {
  154. value = x;
  155. }
  156. }
  157. }
  158. #else
  159. var e = _source.GetAsyncEnumerator(_cancellationToken);
  160. try
  161. {
  162. do
  163. {
  164. if (!await e.MoveNextAsync().ConfigureAwait(false))
  165. {
  166. return value;
  167. }
  168. value = _selector(e.Current);
  169. }
  170. while (value == null);
  171. while (await e.MoveNextAsync().ConfigureAwait(false))
  172. {
  173. var x = _selector(e.Current);
  174. if (x != null && comparer.Compare(x, value) > 0)
  175. {
  176. value = x;
  177. }
  178. }
  179. }
  180. finally
  181. {
  182. await e.DisposeAsync().ConfigureAwait(false);
  183. }
  184. #endif
  185. return value;
  186. }
  187. }
  188. else
  189. {
  190. return Core(source, selector, cancellationToken);
  191. static async Task<TResult> Core(IAsyncEnumerable<TSource> _source, Func<TSource, TResult> _selector, CancellationToken _cancellationToken)
  192. {
  193. var comparer = Comparer<TResult>.Default;
  194. var value = default(TResult);
  195. #if CSHARP8
  196. await using (var e = _source.GetAsyncEnumerator(_cancellationToken).ConfigureAwait(false))
  197. {
  198. if (!await e.MoveNextAsync())
  199. {
  200. throw Error.NoElements();
  201. }
  202. value = _selector(e.Current);
  203. while (await e.MoveNextAsync())
  204. {
  205. var x = _selector(e.Current);
  206. if (comparer.Compare(x, value) > 0)
  207. {
  208. value = x;
  209. }
  210. }
  211. }
  212. #else
  213. var e = _source.GetAsyncEnumerator(_cancellationToken);
  214. try
  215. {
  216. if (!await e.MoveNextAsync().ConfigureAwait(false))
  217. {
  218. throw Error.NoElements();
  219. }
  220. value = _selector(e.Current);
  221. while (await e.MoveNextAsync().ConfigureAwait(false))
  222. {
  223. var x = _selector(e.Current);
  224. if (comparer.Compare(x, value) > 0)
  225. {
  226. value = x;
  227. }
  228. }
  229. }
  230. finally
  231. {
  232. await e.DisposeAsync().ConfigureAwait(false);
  233. }
  234. #endif
  235. return value;
  236. }
  237. }
  238. }
  239. public static Task<TResult> MaxAsync<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, ValueTask<TResult>> selector, CancellationToken cancellationToken = default)
  240. {
  241. if (source == null)
  242. throw Error.ArgumentNull(nameof(source));
  243. if (selector == null)
  244. throw Error.ArgumentNull(nameof(selector));
  245. if (default(TResult) == null)
  246. {
  247. return Core(source, selector, cancellationToken);
  248. static async Task<TResult> Core(IAsyncEnumerable<TSource> _source, Func<TSource, ValueTask<TResult>> _selector, CancellationToken _cancellationToken)
  249. {
  250. var comparer = Comparer<TResult>.Default;
  251. var value = default(TResult);
  252. #if CSHARP8
  253. await using (var e = _source.GetAsyncEnumerator(_cancellationToken).ConfigureAwait(false))
  254. {
  255. do
  256. {
  257. if (!await e.MoveNextAsync())
  258. {
  259. return value;
  260. }
  261. value = await _selector(e.Current).ConfigureAwait(false);
  262. }
  263. while (value == null);
  264. while (await e.MoveNextAsync())
  265. {
  266. var x = await _selector(e.Current).ConfigureAwait(false);
  267. if (x != null && comparer.Compare(x, value) > 0)
  268. {
  269. value = x;
  270. }
  271. }
  272. }
  273. #else
  274. var e = _source.GetAsyncEnumerator(_cancellationToken);
  275. try
  276. {
  277. do
  278. {
  279. if (!await e.MoveNextAsync().ConfigureAwait(false))
  280. {
  281. return value;
  282. }
  283. value = await _selector(e.Current).ConfigureAwait(false);
  284. }
  285. while (value == null);
  286. while (await e.MoveNextAsync().ConfigureAwait(false))
  287. {
  288. var x = await _selector(e.Current).ConfigureAwait(false);
  289. if (x != null && comparer.Compare(x, value) > 0)
  290. {
  291. value = x;
  292. }
  293. }
  294. }
  295. finally
  296. {
  297. await e.DisposeAsync().ConfigureAwait(false);
  298. }
  299. #endif
  300. return value;
  301. }
  302. }
  303. else
  304. {
  305. return Core(source, selector, cancellationToken);
  306. static async Task<TResult> Core(IAsyncEnumerable<TSource> _source, Func<TSource, ValueTask<TResult>> _selector, CancellationToken _cancellationToken)
  307. {
  308. var comparer = Comparer<TResult>.Default;
  309. var value = default(TResult);
  310. #if CSHARP8
  311. await using (var e = _source.GetAsyncEnumerator(_cancellationToken).ConfigureAwait(false))
  312. {
  313. if (!await e.MoveNextAsync())
  314. {
  315. throw Error.NoElements();
  316. }
  317. value = await _selector(e.Current).ConfigureAwait(false);
  318. while (await e.MoveNextAsync())
  319. {
  320. var x = await _selector(e.Current).ConfigureAwait(false);
  321. if (comparer.Compare(x, value) > 0)
  322. {
  323. value = x;
  324. }
  325. }
  326. }
  327. #else
  328. var e = _source.GetAsyncEnumerator(_cancellationToken);
  329. try
  330. {
  331. if (!await e.MoveNextAsync().ConfigureAwait(false))
  332. {
  333. throw Error.NoElements();
  334. }
  335. value = await _selector(e.Current).ConfigureAwait(false);
  336. while (await e.MoveNextAsync().ConfigureAwait(false))
  337. {
  338. var x = await _selector(e.Current).ConfigureAwait(false);
  339. if (comparer.Compare(x, value) > 0)
  340. {
  341. value = x;
  342. }
  343. }
  344. }
  345. finally
  346. {
  347. await e.DisposeAsync().ConfigureAwait(false);
  348. }
  349. #endif
  350. return value;
  351. }
  352. }
  353. }
  354. #if !NO_DEEP_CANCELLATION
  355. public static Task<TResult> MaxAsync<TSource, TResult>(this IAsyncEnumerable<TSource> source, Func<TSource, CancellationToken, ValueTask<TResult>> selector, CancellationToken cancellationToken = default)
  356. {
  357. if (source == null)
  358. throw Error.ArgumentNull(nameof(source));
  359. if (selector == null)
  360. throw Error.ArgumentNull(nameof(selector));
  361. if (default(TResult) == null)
  362. {
  363. return Core(source, selector, cancellationToken);
  364. static async Task<TResult> Core(IAsyncEnumerable<TSource> _source, Func<TSource, CancellationToken, ValueTask<TResult>> _selector, CancellationToken _cancellationToken)
  365. {
  366. var comparer = Comparer<TResult>.Default;
  367. var value = default(TResult);
  368. #if CSHARP8
  369. await using (var e = _source.GetAsyncEnumerator(_cancellationToken).ConfigureAwait(false))
  370. {
  371. do
  372. {
  373. if (!await e.MoveNextAsync())
  374. {
  375. return value;
  376. }
  377. value = await _selector(e.Current, _cancellationToken).ConfigureAwait(false);
  378. }
  379. while (value == null);
  380. while (await e.MoveNextAsync())
  381. {
  382. var x = await _selector(e.Current, _cancellationToken).ConfigureAwait(false);
  383. if (x != null && comparer.Compare(x, value) > 0)
  384. {
  385. value = x;
  386. }
  387. }
  388. }
  389. #else
  390. var e = _source.GetAsyncEnumerator(_cancellationToken);
  391. try
  392. {
  393. do
  394. {
  395. if (!await e.MoveNextAsync().ConfigureAwait(false))
  396. {
  397. return value;
  398. }
  399. value = await _selector(e.Current, _cancellationToken).ConfigureAwait(false);
  400. }
  401. while (value == null);
  402. while (await e.MoveNextAsync().ConfigureAwait(false))
  403. {
  404. var x = await _selector(e.Current, _cancellationToken).ConfigureAwait(false);
  405. if (x != null && comparer.Compare(x, value) > 0)
  406. {
  407. value = x;
  408. }
  409. }
  410. }
  411. finally
  412. {
  413. await e.DisposeAsync().ConfigureAwait(false);
  414. }
  415. #endif
  416. return value;
  417. }
  418. }
  419. else
  420. {
  421. return Core(source, selector, cancellationToken);
  422. static async Task<TResult> Core(IAsyncEnumerable<TSource> _source, Func<TSource, CancellationToken, ValueTask<TResult>> _selector, CancellationToken _cancellationToken)
  423. {
  424. var comparer = Comparer<TResult>.Default;
  425. var value = default(TResult);
  426. #if CSHARP8
  427. await using (var e = _source.GetAsyncEnumerator(_cancellationToken).ConfigureAwait(false))
  428. {
  429. if (!await e.MoveNextAsync())
  430. {
  431. throw Error.NoElements();
  432. }
  433. value = await _selector(e.Current, _cancellationToken).ConfigureAwait(false);
  434. while (await e.MoveNextAsync())
  435. {
  436. var x = await _selector(e.Current, _cancellationToken).ConfigureAwait(false);
  437. if (comparer.Compare(x, value) > 0)
  438. {
  439. value = x;
  440. }
  441. }
  442. }
  443. #else
  444. var e = _source.GetAsyncEnumerator(_cancellationToken);
  445. try
  446. {
  447. if (!await e.MoveNextAsync().ConfigureAwait(false))
  448. {
  449. throw Error.NoElements();
  450. }
  451. value = await _selector(e.Current, _cancellationToken).ConfigureAwait(false);
  452. while (await e.MoveNextAsync().ConfigureAwait(false))
  453. {
  454. var x = await _selector(e.Current, _cancellationToken).ConfigureAwait(false);
  455. if (comparer.Compare(x, value) > 0)
  456. {
  457. value = x;
  458. }
  459. }
  460. }
  461. finally
  462. {
  463. await e.DisposeAsync().ConfigureAwait(false);
  464. }
  465. #endif
  466. return value;
  467. }
  468. }
  469. }
  470. #endif
  471. }
  472. }