// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace System.Linq
{
public static partial class EnumerableEx
{
///
/// Lazily invokes an action for each value in the sequence.
///
/// Source sequence element type.
/// Source sequence.
/// Action to invoke for each element.
/// Sequence exhibiting the specified side-effects upon enumeration.
public static IEnumerable Do(this IEnumerable source, Action onNext)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (onNext == null)
throw new ArgumentNullException(nameof(onNext));
return DoHelper(source, onNext, _ => { }, () => { });
}
///
/// Lazily invokes an action for each value in the sequence, and executes an action for successful termination.
///
/// Source sequence element type.
/// Source sequence.
/// Action to invoke for each element.
/// Action to invoke on successful termination of the sequence.
/// Sequence exhibiting the specified side-effects upon enumeration.
public static IEnumerable Do(this IEnumerable source, Action onNext, Action onCompleted)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (onNext == null)
throw new ArgumentNullException(nameof(onNext));
if (onCompleted == null)
throw new ArgumentNullException(nameof(onCompleted));
return DoHelper(source, onNext, _ => { }, onCompleted);
}
///
/// Lazily invokes an action for each value in the sequence, and executes an action upon exceptional termination.
///
/// Source sequence element type.
/// Source sequence.
/// Action to invoke for each element.
/// Action to invoke on exceptional termination of the sequence.
/// Sequence exhibiting the specified side-effects upon enumeration.
public static IEnumerable Do(this IEnumerable source, Action onNext, Action onError)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (onNext == null)
throw new ArgumentNullException(nameof(onNext));
if (onError == null)
throw new ArgumentNullException(nameof(onError));
return DoHelper(source, onNext, onError, () => { });
}
///
/// Lazily invokes an action for each value in the sequence, and executes an action upon successful or exceptional
/// termination.
///
/// Source sequence element type.
/// Source sequence.
/// Action to invoke for each element.
/// Action to invoke on exceptional termination of the sequence.
/// Action to invoke on successful termination of the sequence.
/// Sequence exhibiting the specified side-effects upon enumeration.
public static IEnumerable Do(this IEnumerable source, Action onNext, Action onError, Action onCompleted)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (onNext == null)
throw new ArgumentNullException(nameof(onNext));
if (onError == null)
throw new ArgumentNullException(nameof(onError));
if (onCompleted == null)
throw new ArgumentNullException(nameof(onCompleted));
return DoHelper(source, onNext, onError, onCompleted);
}
///
/// Lazily invokes observer methods for each value in the sequence, and upon successful or exceptional termination.
///
/// Source sequence element type.
/// Source sequence.
/// Observer to invoke notification calls on.
/// Sequence exhibiting the side-effects of observer method invocation upon enumeration.
public static IEnumerable Do(this IEnumerable source, IObserver observer)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (observer == null)
throw new ArgumentNullException(nameof(observer));
return DoHelper(source, observer.OnNext, observer.OnError, observer.OnCompleted);
}
///
/// Generates an enumerable sequence by repeating a source sequence as long as the given loop postcondition holds.
///
/// Result sequence element type.
/// Source sequence to repeat while the condition evaluates true.
/// Loop condition.
/// Sequence generated by repeating the given sequence until the condition evaluates to false.
public static IEnumerable DoWhile(this IEnumerable source, Func condition)
{
if (source == null)
throw new ArgumentNullException(nameof(source));
if (condition == null)
throw new ArgumentNullException(nameof(condition));
return source.Concat(While(condition, source));
}
private static IEnumerable DoHelper(this IEnumerable source, Action onNext, Action onError, Action onCompleted)
{
using (var e = source.GetEnumerator())
{
while (true)
{
var current = default(TSource);
try
{
if (!e.MoveNext())
break;
current = e.Current;
}
catch (Exception ex)
{
onError(ex);
throw;
}
onNext(current);
yield return current;
}
onCompleted();
}
}
}
}