// 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.Security; using System.Threading.Tasks; namespace System.Linq { /// /// Interface for yielding elements to enumerator. /// /// Type of the elements yielded to an enumerator. public interface IYielder { /// /// Stops the enumeration. /// /// Awaitable object for use in an asynchronous method. IAwaitable Break(); /// /// Yields a value to the enumerator. /// /// Value to yield return. /// Awaitable object for use in an asynchronous method. IAwaitable Return(T value); } internal class Yielder : IYielder, IAwaitable, IAwaiter { private readonly Action> _create; private Action _continuation; private bool _hasValue; private bool _running; private bool _stopped; public Yielder(Action> create) { _create = create; } public T Current { get; private set; } public IAwaiter GetAwaiter() { return this; } public bool IsCompleted { get { return false; } } public void GetResult() { } [SecurityCritical] public void UnsafeOnCompleted(Action continuation) { _continuation = continuation; } public void OnCompleted(Action continuation) { _continuation = continuation; } public IAwaitable Return(T value) { _hasValue = true; Current = value; return this; } public IAwaitable Break() { _stopped = true; return this; } public Yielder GetEnumerator() { return this; } public bool MoveNext() { if (!_running) { _running = true; _create(this); } else { _hasValue = false; _continuation(); } return !_stopped && _hasValue; } public void Reset() { throw new NotSupportedException(); } } }