Select.cs 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819
  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;
  5. using System.Collections;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using System.Threading;
  9. using System.Threading.Tasks;
  10. using Xunit;
  11. namespace Tests
  12. {
  13. public class Select : AsyncEnumerableTests
  14. {
  15. [Fact]
  16. public void Select_Sync_Null()
  17. {
  18. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.Select<int, int>(default, x => x));
  19. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.Select<int, int>(default, (x, i) => x));
  20. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.Select(Return42, default(Func<int, int>)));
  21. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.Select(Return42, default(Func<int, int, int>)));
  22. }
  23. [Fact]
  24. public async Task Select_Sync_Simple()
  25. {
  26. var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
  27. var ys = xs.Select(x => (char)('a' + x));
  28. var e = ys.GetAsyncEnumerator();
  29. await HasNextAsync(e, 'a');
  30. await HasNextAsync(e, 'b');
  31. await HasNextAsync(e, 'c');
  32. await NoNextAsync(e);
  33. }
  34. [Fact]
  35. public async Task Select_Sync_Simple_IList()
  36. {
  37. var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
  38. var ys = xs.Select(x => (char)('a' + x));
  39. var e = ys.GetAsyncEnumerator();
  40. await HasNextAsync(e, 'a');
  41. await HasNextAsync(e, 'b');
  42. await HasNextAsync(e, 'c');
  43. await NoNextAsync(e);
  44. }
  45. [Fact]
  46. public async Task Select_Sync_Simple_AsyncIterator()
  47. {
  48. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  49. var ys = xs.Select(x => (char)('a' + x));
  50. var e = ys.GetAsyncEnumerator();
  51. await HasNextAsync(e, 'a');
  52. await HasNextAsync(e, 'b');
  53. await HasNextAsync(e, 'c');
  54. await NoNextAsync(e);
  55. }
  56. [Fact]
  57. public async Task Select_Sync_Indexed()
  58. {
  59. var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
  60. var ys = xs.Select((x, i) => (char)('a' + i));
  61. var e = ys.GetAsyncEnumerator();
  62. await HasNextAsync(e, 'a');
  63. await HasNextAsync(e, 'b');
  64. await HasNextAsync(e, 'c');
  65. await NoNextAsync(e);
  66. }
  67. [Fact]
  68. public async Task Select_Sync_Indexed_IList()
  69. {
  70. var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
  71. var ys = xs.Select((x, i) => (char)('a' + i));
  72. var e = ys.GetAsyncEnumerator();
  73. await HasNextAsync(e, 'a');
  74. await HasNextAsync(e, 'b');
  75. await HasNextAsync(e, 'c');
  76. await NoNextAsync(e);
  77. }
  78. [Fact]
  79. public async Task Select_Sync_Indexed_AsyncIterator()
  80. {
  81. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  82. var ys = xs.Select((x, i) => (char)('a' + i));
  83. var e = ys.GetAsyncEnumerator();
  84. await HasNextAsync(e, 'a');
  85. await HasNextAsync(e, 'b');
  86. await HasNextAsync(e, 'c');
  87. await NoNextAsync(e);
  88. }
  89. [Fact]
  90. public async Task Select_Sync_Throws_Selector()
  91. {
  92. var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
  93. var ys = xs.Select(x => 1 / x);
  94. var e = ys.GetAsyncEnumerator();
  95. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  96. }
  97. [Fact]
  98. public async Task Select_Sync_Throws_Selector_IList()
  99. {
  100. var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
  101. var ys = xs.Select(x => 1 / x);
  102. var e = ys.GetAsyncEnumerator();
  103. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  104. }
  105. [Fact]
  106. public async Task Select_Sync_Throws_Selector_AsyncIterator()
  107. {
  108. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  109. var ys = xs.Select(x => 1 / x);
  110. var e = ys.GetAsyncEnumerator();
  111. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  112. }
  113. [Fact]
  114. public async Task Select_Sync_Indexed_Throws_Selector()
  115. {
  116. var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
  117. var ys = xs.Select((x, i) => 1 / i);
  118. var e = ys.GetAsyncEnumerator();
  119. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  120. }
  121. [Fact]
  122. public async Task Select_Sync_Indexed_Throws_Selector_IList()
  123. {
  124. var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
  125. var ys = xs.Select((x, i) => 1 / i);
  126. var e = ys.GetAsyncEnumerator();
  127. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  128. }
  129. [Fact]
  130. public async Task Select_Sync_Indexed_Throws_Selector_AsyncIterator()
  131. {
  132. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  133. var ys = xs.Select((x, i) => 1 / i);
  134. var e = ys.GetAsyncEnumerator();
  135. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  136. }
  137. [Fact]
  138. public async Task Select_Sync_SelectSelect()
  139. {
  140. var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
  141. var ys = xs.Select(i => i + 3).Select(x => (char)('a' + x));
  142. var e = ys.GetAsyncEnumerator();
  143. await HasNextAsync(e, 'd');
  144. await HasNextAsync(e, 'e');
  145. await HasNextAsync(e, 'f');
  146. await NoNextAsync(e);
  147. }
  148. [Fact]
  149. public async Task Select_Sync_SelectSelect_IList()
  150. {
  151. var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
  152. var ys = xs.Select(i => i + 3).Select(x => (char)('a' + x));
  153. var e = ys.GetAsyncEnumerator();
  154. await HasNextAsync(e, 'd');
  155. await HasNextAsync(e, 'e');
  156. await HasNextAsync(e, 'f');
  157. await NoNextAsync(e);
  158. }
  159. [Fact]
  160. public async Task Select_Sync_SelectSelect_AsyncIterator()
  161. {
  162. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  163. var ys = xs.Select(i => i + 3).Select(x => (char)('a' + x));
  164. var e = ys.GetAsyncEnumerator();
  165. await HasNextAsync(e, 'd');
  166. await HasNextAsync(e, 'e');
  167. await HasNextAsync(e, 'f');
  168. await NoNextAsync(e);
  169. }
  170. [Fact]
  171. public async Task Select_Sync_SequenceIdentity()
  172. {
  173. var xs = ToAsyncEnumerable(new[] { 1, 2, 3 });
  174. var ys = xs.Select(x => (char)('a' + x));
  175. await SequenceIdentity(ys);
  176. }
  177. [Fact]
  178. public async Task Select_Sync_SequenceIdentity_IList()
  179. {
  180. var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3 });
  181. var ys = xs.Select(x => (char)('a' + x));
  182. await SequenceIdentity(ys);
  183. }
  184. [Fact]
  185. public async Task Select_Sync_SequenceIdentity_AsyncIterator()
  186. {
  187. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  188. var ys = xs.Select(x => (char)('a' + x));
  189. await SequenceIdentity(ys);
  190. }
  191. [Fact]
  192. public async Task Select_Sync_Indexed_SequenceIdentity()
  193. {
  194. var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
  195. var ys = xs.Select((x, i) => (char)('a' + i));
  196. await SequenceIdentity(ys);
  197. }
  198. [Fact]
  199. public async Task Select_Sync_Indexed_SequenceIdentity_IList()
  200. {
  201. var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
  202. var ys = xs.Select((x, i) => (char)('a' + i));
  203. await SequenceIdentity(ys);
  204. }
  205. [Fact]
  206. public async Task Select_Sync_Indexed_SequenceIdentity_AsyncIterator()
  207. {
  208. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  209. var ys = xs.Select((x, i) => (char)('a' + i));
  210. await SequenceIdentity(ys);
  211. }
  212. [Fact]
  213. public void Select_Async_Null()
  214. {
  215. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.Select<int, int>(default, x => new ValueTask<int>(x)));
  216. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.Select(default, (int x, int i) => new ValueTask<int>(x)));
  217. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.Select(Return42, default(Func<int, ValueTask<int>>)));
  218. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.Select(Return42, default(Func<int, int, ValueTask<int>>)));
  219. }
  220. [Fact]
  221. public async Task Select_Async_Simple()
  222. {
  223. var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
  224. var ys = xs.Select(x => new ValueTask<char>((char)('a' + x)));
  225. var e = ys.GetAsyncEnumerator();
  226. await HasNextAsync(e, 'a');
  227. await HasNextAsync(e, 'b');
  228. await HasNextAsync(e, 'c');
  229. await NoNextAsync(e);
  230. }
  231. [Fact]
  232. public async Task Select_Async_Simple_IList()
  233. {
  234. var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
  235. var ys = xs.Select(x => new ValueTask<char>((char)('a' + x)));
  236. var e = ys.GetAsyncEnumerator();
  237. await HasNextAsync(e, 'a');
  238. await HasNextAsync(e, 'b');
  239. await HasNextAsync(e, 'c');
  240. await NoNextAsync(e);
  241. }
  242. [Fact]
  243. public async Task Select_Async_Simple_AsyncIterator()
  244. {
  245. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  246. var ys = xs.Select(x => new ValueTask<char>((char)('a' + x)));
  247. var e = ys.GetAsyncEnumerator();
  248. await HasNextAsync(e, 'a');
  249. await HasNextAsync(e, 'b');
  250. await HasNextAsync(e, 'c');
  251. await NoNextAsync(e);
  252. }
  253. [Fact]
  254. public async Task Select_Async_Indexed()
  255. {
  256. var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
  257. var ys = xs.Select((x, i) => new ValueTask<char>((char)('a' + i)));
  258. var e = ys.GetAsyncEnumerator();
  259. await HasNextAsync(e, 'a');
  260. await HasNextAsync(e, 'b');
  261. await HasNextAsync(e, 'c');
  262. await NoNextAsync(e);
  263. }
  264. [Fact]
  265. public async Task Select_Async_Indexed_IList()
  266. {
  267. var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
  268. var ys = xs.Select((x, i) => new ValueTask<char>((char)('a' + i)));
  269. var e = ys.GetAsyncEnumerator();
  270. await HasNextAsync(e, 'a');
  271. await HasNextAsync(e, 'b');
  272. await HasNextAsync(e, 'c');
  273. await NoNextAsync(e);
  274. }
  275. [Fact]
  276. public async Task Select_Async_Indexed_AsyncIterator()
  277. {
  278. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  279. var ys = xs.Select((x, i) => new ValueTask<char>((char)('a' + i)));
  280. var e = ys.GetAsyncEnumerator();
  281. await HasNextAsync(e, 'a');
  282. await HasNextAsync(e, 'b');
  283. await HasNextAsync(e, 'c');
  284. await NoNextAsync(e);
  285. }
  286. [Fact]
  287. public async Task Select_Async_Throws_Selector()
  288. {
  289. var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
  290. var ys = xs.Select(x => new ValueTask<int>(1 / x));
  291. var e = ys.GetAsyncEnumerator();
  292. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  293. }
  294. [Fact]
  295. public async Task Select_Async_Throws_Selector_IList()
  296. {
  297. var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
  298. var ys = xs.Select(x => new ValueTask<int>(1 / x));
  299. var e = ys.GetAsyncEnumerator();
  300. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  301. }
  302. [Fact]
  303. public async Task Select_Async_Throws_Selector_AsyncIterator()
  304. {
  305. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  306. var ys = xs.Select(x => new ValueTask<int>(1 / x));
  307. var e = ys.GetAsyncEnumerator();
  308. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  309. }
  310. [Fact]
  311. public async Task Select_Async_Indexed_Throws_Selector()
  312. {
  313. var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
  314. var ys = xs.Select((x, i) => new ValueTask<int>(1 / i));
  315. var e = ys.GetAsyncEnumerator();
  316. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  317. }
  318. [Fact]
  319. public async Task Select_Async_Indexed_Throws_Selector_IList()
  320. {
  321. var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
  322. var ys = xs.Select((x, i) => new ValueTask<int>(1 / i));
  323. var e = ys.GetAsyncEnumerator();
  324. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  325. }
  326. [Fact]
  327. public async Task Select_Async_Indexed_Throws_Selector_AsyncIterator()
  328. {
  329. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  330. var ys = xs.Select((x, i) => new ValueTask<int>(1 / i));
  331. var e = ys.GetAsyncEnumerator();
  332. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  333. }
  334. [Fact]
  335. public async Task Select_Async_SelectSelect()
  336. {
  337. var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
  338. var ys = xs.Select(i => new ValueTask<int>(i + 3)).Select(x => new ValueTask<char>((char)('a' + x)));
  339. var e = ys.GetAsyncEnumerator();
  340. await HasNextAsync(e, 'd');
  341. await HasNextAsync(e, 'e');
  342. await HasNextAsync(e, 'f');
  343. await NoNextAsync(e);
  344. }
  345. [Fact]
  346. public async Task Select_Async_SelectSelect_IList()
  347. {
  348. var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
  349. var ys = xs.Select(i => new ValueTask<int>(i + 3)).Select(x => new ValueTask<char>((char)('a' + x)));
  350. var e = ys.GetAsyncEnumerator();
  351. await HasNextAsync(e, 'd');
  352. await HasNextAsync(e, 'e');
  353. await HasNextAsync(e, 'f');
  354. await NoNextAsync(e);
  355. }
  356. [Fact]
  357. public async Task Select_Async_SelectSelect_AsyncIterator()
  358. {
  359. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  360. var ys = xs.Select(i => new ValueTask<int>(i + 3)).Select(x => new ValueTask<char>((char)('a' + x)));
  361. var e = ys.GetAsyncEnumerator();
  362. await HasNextAsync(e, 'd');
  363. await HasNextAsync(e, 'e');
  364. await HasNextAsync(e, 'f');
  365. await NoNextAsync(e);
  366. }
  367. [Fact]
  368. public async Task Select_Async_SequenceIdentity()
  369. {
  370. var xs = ToAsyncEnumerable(new[] { 1, 2, 3 });
  371. var ys = xs.Select(x => new ValueTask<char>((char)('a' + x)));
  372. await SequenceIdentity(ys);
  373. }
  374. [Fact]
  375. public async Task Select_Async_SequenceIdentity_IList()
  376. {
  377. var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3 });
  378. var ys = xs.Select(x => new ValueTask<char>((char)('a' + x)));
  379. await SequenceIdentity(ys);
  380. }
  381. [Fact]
  382. public async Task Select_Async_SequenceIdentity_AsyncIterator()
  383. {
  384. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  385. var ys = xs.Select(x => new ValueTask<char>((char)('a' + x)));
  386. await SequenceIdentity(ys);
  387. }
  388. [Fact]
  389. public async Task Select_Async_Indexed_SequenceIdentity()
  390. {
  391. var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
  392. var ys = xs.Select((x, i) => new ValueTask<char>((char)('a' + i)));
  393. await SequenceIdentity(ys);
  394. }
  395. [Fact]
  396. public async Task Select_Async_Indexed_SequenceIdentity_IList()
  397. {
  398. var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
  399. var ys = xs.Select((x, i) => new ValueTask<char>((char)('a' + i)));
  400. await SequenceIdentity(ys);
  401. }
  402. [Fact]
  403. public async Task Select_Async_Indexed_SequenceIdentity_AsyncIterator()
  404. {
  405. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  406. var ys = xs.Select((x, i) => new ValueTask<char>((char)('a' + i)));
  407. await SequenceIdentity(ys);
  408. }
  409. #if !NO_DEEP_CANCELLATION
  410. // REVIEW: These overloads are problematic for type inference. E.g. xs.Select((x, ct) => ...) is ambiguous.
  411. [Fact]
  412. public void Select_Async_Cancel_Null()
  413. {
  414. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.Select(default, (int x, CancellationToken ct) => new ValueTask<int>(x)));
  415. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.Select(default, (int x, int i, CancellationToken ct) => new ValueTask<int>(x)));
  416. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.Select(Return42, default(Func<int, CancellationToken, ValueTask<int>>)));
  417. Assert.Throws<ArgumentNullException>(() => AsyncEnumerable.Select(Return42, default(Func<int, int, CancellationToken, ValueTask<int>>)));
  418. }
  419. [Fact]
  420. public async Task Select_Async_Cancel_Simple()
  421. {
  422. var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
  423. var ys = xs.Select((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  424. var e = ys.GetAsyncEnumerator();
  425. await HasNextAsync(e, 'a');
  426. await HasNextAsync(e, 'b');
  427. await HasNextAsync(e, 'c');
  428. await NoNextAsync(e);
  429. }
  430. [Fact]
  431. public async Task Select_Async_Cancel_Simple_IList()
  432. {
  433. var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
  434. var ys = xs.Select((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  435. var e = ys.GetAsyncEnumerator();
  436. await HasNextAsync(e, 'a');
  437. await HasNextAsync(e, 'b');
  438. await HasNextAsync(e, 'c');
  439. await NoNextAsync(e);
  440. }
  441. [Fact]
  442. public async Task Select_Async_Cancel_Simple_Async_CancelIterator()
  443. {
  444. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  445. var ys = xs.Select((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  446. var e = ys.GetAsyncEnumerator();
  447. await HasNextAsync(e, 'a');
  448. await HasNextAsync(e, 'b');
  449. await HasNextAsync(e, 'c');
  450. await NoNextAsync(e);
  451. }
  452. [Fact]
  453. public async Task Select_Async_Cancel_Indexed()
  454. {
  455. var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
  456. var ys = xs.Select((x, i, ct) => new ValueTask<char>((char)('a' + i)));
  457. var e = ys.GetAsyncEnumerator();
  458. await HasNextAsync(e, 'a');
  459. await HasNextAsync(e, 'b');
  460. await HasNextAsync(e, 'c');
  461. await NoNextAsync(e);
  462. }
  463. [Fact]
  464. public async Task Select_Async_Cancel_Indexed_IList()
  465. {
  466. var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
  467. var ys = xs.Select((x, i, ct) => new ValueTask<char>((char)('a' + i)));
  468. var e = ys.GetAsyncEnumerator();
  469. await HasNextAsync(e, 'a');
  470. await HasNextAsync(e, 'b');
  471. await HasNextAsync(e, 'c');
  472. await NoNextAsync(e);
  473. }
  474. [Fact]
  475. public async Task Select_Async_Cancel_Indexed_Async_CancelIterator()
  476. {
  477. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  478. var ys = xs.Select((x, i, ct) => new ValueTask<char>((char)('a' + i)));
  479. var e = ys.GetAsyncEnumerator();
  480. await HasNextAsync(e, 'a');
  481. await HasNextAsync(e, 'b');
  482. await HasNextAsync(e, 'c');
  483. await NoNextAsync(e);
  484. }
  485. [Fact]
  486. public async Task Select_Async_Cancel_Throws_Selector()
  487. {
  488. var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
  489. var ys = xs.Select((int x, CancellationToken ct) => new ValueTask<int>(1 / x));
  490. var e = ys.GetAsyncEnumerator();
  491. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  492. }
  493. [Fact]
  494. public async Task Select_Async_Cancel_Throws_Selector_IList()
  495. {
  496. var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
  497. var ys = xs.Select((int x, CancellationToken ct) => new ValueTask<int>(1 / x));
  498. var e = ys.GetAsyncEnumerator();
  499. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  500. }
  501. [Fact]
  502. public async Task Select_Async_Cancel_Throws_Selector_Async_CancelIterator()
  503. {
  504. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  505. var ys = xs.Select((int x, CancellationToken ct) => new ValueTask<int>(1 / x));
  506. var e = ys.GetAsyncEnumerator();
  507. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  508. }
  509. [Fact]
  510. public async Task Select_Async_Cancel_Indexed_Throws_Selector()
  511. {
  512. var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
  513. var ys = xs.Select((x, i, ct) => new ValueTask<int>(1 / i));
  514. var e = ys.GetAsyncEnumerator();
  515. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  516. }
  517. [Fact]
  518. public async Task Select_Async_Cancel_Indexed_Throws_Selector_IList()
  519. {
  520. var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
  521. var ys = xs.Select((x, i, ct) => new ValueTask<int>(1 / i));
  522. var e = ys.GetAsyncEnumerator();
  523. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  524. }
  525. [Fact]
  526. public async Task Select_Async_Cancel_Indexed_Throws_Selector_Async_CancelIterator()
  527. {
  528. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  529. var ys = xs.Select((x, i, ct) => new ValueTask<int>(1 / i));
  530. var e = ys.GetAsyncEnumerator();
  531. await AssertThrowsAsync<DivideByZeroException>(e.MoveNextAsync().AsTask());
  532. }
  533. [Fact]
  534. public async Task Select_Async_Cancel_SelectSelect()
  535. {
  536. var xs = ToAsyncEnumerable(new[] { 0, 1, 2 });
  537. var ys = xs.Select((int i, CancellationToken ct) => new ValueTask<int>(i + 3)).Select((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  538. var e = ys.GetAsyncEnumerator();
  539. await HasNextAsync(e, 'd');
  540. await HasNextAsync(e, 'e');
  541. await HasNextAsync(e, 'f');
  542. await NoNextAsync(e);
  543. }
  544. [Fact]
  545. public async Task Select_Async_Cancel_SelectSelect_IList()
  546. {
  547. var xs = ToAsyncEnumerableIList(new[] { 0, 1, 2 });
  548. var ys = xs.Select((int i, CancellationToken ct) => new ValueTask<int>(i + 3)).Select((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  549. var e = ys.GetAsyncEnumerator();
  550. await HasNextAsync(e, 'd');
  551. await HasNextAsync(e, 'e');
  552. await HasNextAsync(e, 'f');
  553. await NoNextAsync(e);
  554. }
  555. [Fact]
  556. public async Task Select_Async_Cancel_SelectSelect_Async_CancelIterator()
  557. {
  558. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  559. var ys = xs.Select((int i, CancellationToken ct) => new ValueTask<int>(i + 3)).Select((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  560. var e = ys.GetAsyncEnumerator();
  561. await HasNextAsync(e, 'd');
  562. await HasNextAsync(e, 'e');
  563. await HasNextAsync(e, 'f');
  564. await NoNextAsync(e);
  565. }
  566. [Fact]
  567. public async Task Select_Async_Cancel_SequenceIdentity()
  568. {
  569. var xs = ToAsyncEnumerable(new[] { 1, 2, 3 });
  570. var ys = xs.Select((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  571. await SequenceIdentity(ys);
  572. }
  573. [Fact]
  574. public async Task Select_Async_Cancel_SequenceIdentity_IList()
  575. {
  576. var xs = ToAsyncEnumerableIList(new[] { 1, 2, 3 });
  577. var ys = xs.Select((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  578. await SequenceIdentity(ys);
  579. }
  580. [Fact]
  581. public async Task Select_Async_Cancel_SequenceIdentity_Async_CancelIterator()
  582. {
  583. var xs = new[] { 0, 1, 2 }.ToAsyncEnumerable();
  584. var ys = xs.Select((int x, CancellationToken ct) => new ValueTask<char>((char)('a' + x)));
  585. await SequenceIdentity(ys);
  586. }
  587. [Fact]
  588. public async Task Select_Async_Cancel_Indexed_SequenceIdentity()
  589. {
  590. var xs = ToAsyncEnumerable(new[] { 8, 5, 7 });
  591. var ys = xs.Select((x, i, ct) => new ValueTask<char>((char)('a' + i)));
  592. await SequenceIdentity(ys);
  593. }
  594. [Fact]
  595. public async Task Select_Async_Cancel_Indexed_SequenceIdentity_IList()
  596. {
  597. var xs = ToAsyncEnumerableIList(new[] { 8, 5, 7 });
  598. var ys = xs.Select((x, i, ct) => new ValueTask<char>((char)('a' + i)));
  599. await SequenceIdentity(ys);
  600. }
  601. [Fact]
  602. public async Task Select_Async_Cancel_Indexed_SequenceIdentity_Async_CancelIterator()
  603. {
  604. var xs = new[] { 8, 5, 7 }.ToAsyncEnumerable();
  605. var ys = xs.Select((x, i, ct) => new ValueTask<char>((char)('a' + i)));
  606. await SequenceIdentity(ys);
  607. }
  608. #endif
  609. private static IAsyncEnumerable<int> ToAsyncEnumerable(int[] xs) => new MyIterator(xs);
  610. private class MyIterator : IAsyncEnumerable<int>
  611. {
  612. private readonly int[] _xs;
  613. public MyIterator(int[] xs) => _xs = xs;
  614. public IAsyncEnumerator<int> GetAsyncEnumerator(CancellationToken cancellationToken = default) => new Enumerator(this);
  615. private class Enumerator : IAsyncEnumerator<int>
  616. {
  617. private readonly MyIterator _parent;
  618. private int _i = -1;
  619. public Enumerator(MyIterator parent) => _parent = parent;
  620. public int Current => _parent._xs[_i];
  621. public ValueTask DisposeAsync() => new ValueTask();
  622. public ValueTask<bool> MoveNextAsync() => new ValueTask<bool>(++_i < _parent._xs.Length);
  623. }
  624. }
  625. private static IAsyncEnumerable<int> ToAsyncEnumerableIList(int[] xs) => new MyIteratorIList(xs);
  626. private class MyIteratorIList : IAsyncEnumerable<int>, IList<int>
  627. {
  628. private readonly int[] _xs;
  629. public MyIteratorIList(int[] xs) => _xs = xs;
  630. public int this[int index] { get => _xs[index]; set => throw new NotImplementedException(); }
  631. public int Count => _xs.Length;
  632. public bool IsReadOnly => true;
  633. public void Add(int item) => throw new NotImplementedException();
  634. public void Clear() => throw new NotImplementedException();
  635. public bool Contains(int item) => Array.IndexOf(_xs, item) >= 0;
  636. public void CopyTo(int[] array, int arrayIndex) => throw new NotImplementedException();
  637. public IAsyncEnumerator<int> GetAsyncEnumerator(CancellationToken cancellationToken = default) => new Enumerator(this);
  638. public IEnumerator<int> GetEnumerator() => _xs.AsEnumerable().GetEnumerator();
  639. public int IndexOf(int item) => Array.IndexOf(_xs, item);
  640. public void Insert(int index, int item) => throw new NotImplementedException();
  641. public bool Remove(int item) => throw new NotImplementedException();
  642. public void RemoveAt(int index) => throw new NotImplementedException();
  643. IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
  644. private class Enumerator : IAsyncEnumerator<int>
  645. {
  646. private readonly MyIteratorIList _parent;
  647. private int _i = -1;
  648. public Enumerator(MyIteratorIList parent) => _parent = parent;
  649. public int Current => _parent._xs[_i];
  650. public ValueTask DisposeAsync() => new ValueTask();
  651. public ValueTask<bool> MoveNextAsync() => new ValueTask<bool>(++_i < _parent._xs.Length);
  652. }
  653. }
  654. }
  655. }