Repeat.cs 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  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 IAsyncEnumerable<TResult> Repeat<TResult>(TResult element, int count)
  12. {
  13. if (count < 0)
  14. throw Error.ArgumentOutOfRange(nameof(count));
  15. return new RepeatAsyncIterator<TResult>(element, count);
  16. }
  17. private sealed class RepeatAsyncIterator<TResult> : AsyncIterator<TResult>, IAsyncIListProvider<TResult>
  18. {
  19. private readonly TResult _element;
  20. private readonly int _count;
  21. private int _remaining;
  22. public RepeatAsyncIterator(TResult element, int count)
  23. {
  24. _element = element;
  25. _count = count;
  26. }
  27. public override AsyncIteratorBase<TResult> Clone() => new RepeatAsyncIterator<TResult>(_element, _count);
  28. public Task<int> GetCountAsync(bool onlyIfCheap, CancellationToken cancellationToken) => Task.FromResult(_count);
  29. public Task<TResult[]> ToArrayAsync(CancellationToken cancellationToken)
  30. {
  31. var res = new TResult[_count];
  32. for (var i = 0; i < _count; i++)
  33. {
  34. res[i] = _element;
  35. }
  36. return Task.FromResult(res);
  37. }
  38. public Task<List<TResult>> ToListAsync(CancellationToken cancellationToken)
  39. {
  40. var res = new List<TResult>(_count);
  41. for (var i = 0; i < _count; i++)
  42. {
  43. res.Add(_element);
  44. }
  45. return Task.FromResult(res);
  46. }
  47. protected override async ValueTask<bool> MoveNextCore()
  48. {
  49. switch (_state)
  50. {
  51. case AsyncIteratorState.Allocated:
  52. _remaining = _count;
  53. if (_remaining > 0)
  54. {
  55. _current = _element;
  56. }
  57. _state = AsyncIteratorState.Iterating;
  58. goto case AsyncIteratorState.Iterating;
  59. case AsyncIteratorState.Iterating:
  60. if (_remaining-- != 0)
  61. {
  62. return true;
  63. }
  64. break;
  65. }
  66. await DisposeAsync().ConfigureAwait(false);
  67. return false;
  68. }
  69. }
  70. }
  71. }