| File: System\Collections\Immutable\ImmutableStack_1.Enumerator.cs | Web Access |
| Project: src\runtime\src\libraries\System.Collections.Immutable\src\System.Collections.Immutable.csproj (System.Collections.Immutable) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.ComponentModel; namespace System.Collections.Immutable { public sealed partial class ImmutableStack<T> { /// <summary> /// Enumerates a stack with no memory allocations. /// </summary> [EditorBrowsable(EditorBrowsableState.Advanced)] public struct Enumerator { /// <summary> /// The original stack being enumerated. /// </summary> private readonly ImmutableStack<T> _originalStack; /// <summary> /// The remaining stack not yet enumerated. /// </summary> private ImmutableStack<T>? _remainingStack; /// <summary> /// Initializes a new instance of the <see cref="Enumerator"/> struct. /// </summary> /// <param name="stack">The stack to enumerator.</param> internal Enumerator(ImmutableStack<T> stack) { Requires.NotNull(stack, nameof(stack)); _originalStack = stack; _remainingStack = null; } /// <summary> /// Gets the current element. /// </summary> public T Current { get { if (_remainingStack == null || _remainingStack.IsEmpty) { ThrowHelper.ThrowInvalidOperationException(); } return _remainingStack.Peek(); } } /// <summary> /// Moves to the first or next element. /// </summary> /// <returns>A value indicating whether there are any more elements.</returns> public bool MoveNext() { if (_remainingStack == null) { // initial move _remainingStack = _originalStack; } else if (!_remainingStack.IsEmpty) { _remainingStack = _remainingStack.Pop(); } return !_remainingStack.IsEmpty; } } /// <summary> /// Enumerates a stack with no memory allocations. /// </summary> private sealed class EnumeratorObject : IEnumerator<T> { /// <summary> /// The original stack being enumerated. /// </summary> private readonly ImmutableStack<T> _originalStack; /// <summary> /// The remaining stack not yet enumerated. /// </summary> private ImmutableStack<T>? _remainingStack; /// <summary> /// A flag indicating whether this enumerator has been disposed. /// </summary> private bool _disposed; /// <summary> /// Initializes a new instance of the <see cref="EnumeratorObject"/> class. /// </summary> /// <param name="stack">The stack to enumerator.</param> internal EnumeratorObject(ImmutableStack<T> stack) { Requires.NotNull(stack, nameof(stack)); _originalStack = stack; } /// <summary> /// Gets the current element. /// </summary> public T Current { get { this.ThrowIfDisposed(); if (_remainingStack == null || _remainingStack.IsEmpty) { ThrowHelper.ThrowInvalidOperationException(); } return _remainingStack.Peek(); } } /// <summary> /// Gets the current element. /// </summary> object? IEnumerator.Current { get { return this.Current; } } /// <summary> /// Moves to the first or next element. /// </summary> /// <returns>A value indicating whether there are any more elements.</returns> public bool MoveNext() { this.ThrowIfDisposed(); if (_remainingStack == null) { // initial move _remainingStack = _originalStack; } else if (!_remainingStack.IsEmpty) { _remainingStack = _remainingStack.Pop(); } return !_remainingStack.IsEmpty; } /// <summary> /// Resets the position to just before the first element in the list. /// </summary> public void Reset() { this.ThrowIfDisposed(); _remainingStack = null; } /// <summary> /// Disposes this instance. /// </summary> public void Dispose() { _disposed = true; } /// <summary> /// Throws an <see cref="ObjectDisposedException"/> if this /// enumerator has already been disposed. /// </summary> private void ThrowIfDisposed() { if (_disposed) { Requires.FailObjectDisposed(this); } } } } }