Repeat.cs 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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 ValueTask<int> GetCountAsync(bool onlyIfCheap, CancellationToken cancellationToken) => new ValueTask<int>(_count);
  29. public ValueTask<TResult[]> ToArrayAsync(CancellationToken cancellationToken)
  30. {
  31. cancellationToken.ThrowIfCancellationRequested();
  32. var res = new TResult[_count];
  33. for (var i = 0; i < _count; i++)
  34. {
  35. res[i] = _element;
  36. }
  37. return new ValueTask<TResult[]>(res);
  38. }
  39. public ValueTask<List<TResult>> ToListAsync(CancellationToken cancellationToken)
  40. {
  41. cancellationToken.ThrowIfCancellationRequested();
  42. var res = new List<TResult>(_count);
  43. for (var i = 0; i < _count; i++)
  44. {
  45. res.Add(_element);
  46. }
  47. return new ValueTask<List<TResult>>(res);
  48. }
  49. protected override async ValueTask<bool> MoveNextCore()
  50. {
  51. switch (_state)
  52. {
  53. case AsyncIteratorState.Allocated:
  54. _remaining = _count;
  55. if (_remaining > 0)
  56. {
  57. _current = _element;
  58. }
  59. _state = AsyncIteratorState.Iterating;
  60. goto case AsyncIteratorState.Iterating;
  61. case AsyncIteratorState.Iterating:
  62. if (_remaining-- != 0)
  63. {
  64. return true;
  65. }
  66. break;
  67. }
  68. await DisposeAsync().ConfigureAwait(false);
  69. return false;
  70. }
  71. }
  72. }
  73. }