// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT License.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
namespace System.Linq
{
public static partial class AsyncEnumerableEx
{
///
/// Returns an async-enumerable sequence that terminates with an exception.
///
/// The type used for the type parameter of the resulting sequence.
/// Exception object used for the sequence's termination.
/// The async-enumerable sequence that terminates exceptionally with the specified exception object.
/// is null.
public static IAsyncEnumerable Throw(Exception exception)
{
if (exception == null)
throw Error.ArgumentNull(nameof(exception));
#if NO_TASK_FROMEXCEPTION
var tcs = new TaskCompletionSource();
tcs.TrySetException(exception);
var moveNextThrows = new ValueTask(tcs.Task);
#else
var moveNextThrows = new ValueTask(Task.FromException(exception));
#endif
return new ThrowEnumerable(moveNextThrows);
}
private sealed class ThrowEnumerable : IAsyncEnumerable
{
private readonly ValueTask _moveNextThrows;
public ThrowEnumerable(ValueTask moveNextThrows)
{
_moveNextThrows = moveNextThrows;
}
public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested(); // NB: [LDM-2018-11-28] Equivalent to async iterator behavior.
return new ThrowEnumerator(_moveNextThrows);
}
private sealed class ThrowEnumerator : IAsyncEnumerator
{
private ValueTask _moveNextThrows;
public ThrowEnumerator(ValueTask moveNextThrows)
{
_moveNextThrows = moveNextThrows;
}
public TValue Current => default!;
public ValueTask DisposeAsync()
{
_moveNextThrows = new ValueTask(false);
return default;
}
public ValueTask MoveNextAsync()
{
var result = _moveNextThrows;
_moveNextThrows = new ValueTask(false);
return result;
}
}
}
}
}