Do.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  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.Generic;
  6. using System.Linq;
  7. using System.Threading.Tasks;
  8. namespace System.Linq
  9. {
  10. public static partial class EnumerableEx
  11. {
  12. /// <summary>
  13. /// Lazily invokes an action for each value in the sequence.
  14. /// </summary>
  15. /// <typeparam name="TSource">Source sequence element type.</typeparam>
  16. /// <param name="source">Source sequence.</param>
  17. /// <param name="onNext">Action to invoke for each element.</param>
  18. /// <returns>Sequence exhibiting the specified side-effects upon enumeration.</returns>
  19. public static IEnumerable<TSource> Do<TSource>(this IEnumerable<TSource> source, Action<TSource> onNext)
  20. {
  21. if (source == null)
  22. throw new ArgumentNullException(nameof(source));
  23. if (onNext == null)
  24. throw new ArgumentNullException(nameof(onNext));
  25. return DoHelper(source, onNext, _ => { }, () => { });
  26. }
  27. /// <summary>
  28. /// Lazily invokes an action for each value in the sequence, and executes an action for successful termination.
  29. /// </summary>
  30. /// <typeparam name="TSource">Source sequence element type.</typeparam>
  31. /// <param name="source">Source sequence.</param>
  32. /// <param name="onNext">Action to invoke for each element.</param>
  33. /// <param name="onCompleted">Action to invoke on successful termination of the sequence.</param>
  34. /// <returns>Sequence exhibiting the specified side-effects upon enumeration.</returns>
  35. public static IEnumerable<TSource> Do<TSource>(this IEnumerable<TSource> source, Action<TSource> onNext, Action onCompleted)
  36. {
  37. if (source == null)
  38. throw new ArgumentNullException(nameof(source));
  39. if (onNext == null)
  40. throw new ArgumentNullException(nameof(onNext));
  41. if (onCompleted == null)
  42. throw new ArgumentNullException(nameof(onCompleted));
  43. return DoHelper(source, onNext, _ => { }, onCompleted);
  44. }
  45. /// <summary>
  46. /// Lazily invokes an action for each value in the sequence, and executes an action upon exceptional termination.
  47. /// </summary>
  48. /// <typeparam name="TSource">Source sequence element type.</typeparam>
  49. /// <param name="source">Source sequence.</param>
  50. /// <param name="onNext">Action to invoke for each element.</param>
  51. /// <param name="onError">Action to invoke on exceptional termination of the sequence.</param>
  52. /// <returns>Sequence exhibiting the specified side-effects upon enumeration.</returns>
  53. public static IEnumerable<TSource> Do<TSource>(this IEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError)
  54. {
  55. if (source == null)
  56. throw new ArgumentNullException(nameof(source));
  57. if (onNext == null)
  58. throw new ArgumentNullException(nameof(onNext));
  59. if (onError == null)
  60. throw new ArgumentNullException(nameof(onError));
  61. return DoHelper(source, onNext, onError, () => { });
  62. }
  63. /// <summary>
  64. /// Lazily invokes an action for each value in the sequence, and executes an action upon successful or exceptional
  65. /// termination.
  66. /// </summary>
  67. /// <typeparam name="TSource">Source sequence element type.</typeparam>
  68. /// <param name="source">Source sequence.</param>
  69. /// <param name="onNext">Action to invoke for each element.</param>
  70. /// <param name="onError">Action to invoke on exceptional termination of the sequence.</param>
  71. /// <param name="onCompleted">Action to invoke on successful termination of the sequence.</param>
  72. /// <returns>Sequence exhibiting the specified side-effects upon enumeration.</returns>
  73. public static IEnumerable<TSource> Do<TSource>(this IEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted)
  74. {
  75. if (source == null)
  76. throw new ArgumentNullException(nameof(source));
  77. if (onNext == null)
  78. throw new ArgumentNullException(nameof(onNext));
  79. if (onError == null)
  80. throw new ArgumentNullException(nameof(onError));
  81. if (onCompleted == null)
  82. throw new ArgumentNullException(nameof(onCompleted));
  83. return DoHelper(source, onNext, onError, onCompleted);
  84. }
  85. /// <summary>
  86. /// Lazily invokes observer methods for each value in the sequence, and upon successful or exceptional termination.
  87. /// </summary>
  88. /// <typeparam name="TSource">Source sequence element type.</typeparam>
  89. /// <param name="source">Source sequence.</param>
  90. /// <param name="observer">Observer to invoke notification calls on.</param>
  91. /// <returns>Sequence exhibiting the side-effects of observer method invocation upon enumeration.</returns>
  92. public static IEnumerable<TSource> Do<TSource>(this IEnumerable<TSource> source, IObserver<TSource> observer)
  93. {
  94. if (source == null)
  95. throw new ArgumentNullException(nameof(source));
  96. if (observer == null)
  97. throw new ArgumentNullException(nameof(observer));
  98. return DoHelper(source, observer.OnNext, observer.OnError, observer.OnCompleted);
  99. }
  100. /// <summary>
  101. /// Generates an enumerable sequence by repeating a source sequence as long as the given loop postcondition holds.
  102. /// </summary>
  103. /// <typeparam name="TResult">Result sequence element type.</typeparam>
  104. /// <param name="source">Source sequence to repeat while the condition evaluates true.</param>
  105. /// <param name="condition">Loop condition.</param>
  106. /// <returns>Sequence generated by repeating the given sequence until the condition evaluates to false.</returns>
  107. public static IEnumerable<TResult> DoWhile<TResult>(this IEnumerable<TResult> source, Func<bool> condition)
  108. {
  109. if (source == null)
  110. throw new ArgumentNullException(nameof(source));
  111. if (condition == null)
  112. throw new ArgumentNullException(nameof(condition));
  113. return source.Concat(While(condition, source));
  114. }
  115. private static IEnumerable<TSource> DoHelper<TSource>(this IEnumerable<TSource> source, Action<TSource> onNext, Action<Exception> onError, Action onCompleted)
  116. {
  117. using (var e = source.GetEnumerator())
  118. {
  119. while (true)
  120. {
  121. var current = default(TSource);
  122. try
  123. {
  124. if (!e.MoveNext())
  125. break;
  126. current = e.Current;
  127. }
  128. catch (Exception ex)
  129. {
  130. onError(ex);
  131. throw;
  132. }
  133. onNext(current);
  134. yield return current;
  135. }
  136. onCompleted();
  137. }
  138. }
  139. }
  140. }