File: System\Linq\Select.SizeOpt.cs
Web Access
Project: src\src\libraries\System.Linq\src\System.Linq.csproj (System.Linq)
// 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;
using System.Collections.Generic;
using System.Diagnostics;
 
namespace System.Linq
{
    public static partial class Enumerable
    {
        private sealed class SizeOptIListSelectIterator<TSource, TResult>(IList<TSource> _source, Func<TSource, TResult> _selector)
            : Iterator<TResult>
        {
            private IEnumerator<TSource>? _enumerator;
 
            public override int GetCount(bool onlyIfCheap)
            {
                // In case someone uses Count() to force evaluation of
                // the selector, run it provided `onlyIfCheap` is false.
 
                if (onlyIfCheap)
                {
                    return -1;
                }
 
                int count = 0;
 
                foreach (TSource item in _source)
                {
                    _selector(item);
                    checked
                    {
                        count++;
                    }
                }
 
                return count;
            }
 
            public override Iterator<TResult> Skip(int count)
            {
                Debug.Assert(count > 0);
                return new IListSkipTakeSelectIterator<TSource, TResult>(_source, _selector, count, int.MaxValue);
            }
 
            public override Iterator<TResult> Take(int count)
            {
                Debug.Assert(count > 0);
                return new IListSkipTakeSelectIterator<TSource, TResult>(_source, _selector, 0, count - 1);
            }
 
            public override bool MoveNext()
            {
                switch (_state)
                {
                    case 1:
                        _enumerator = _source.GetEnumerator();
                        _state = 2;
                        goto case 2;
                    case 2:
                        Debug.Assert(_enumerator is not null);
                        if (_enumerator.MoveNext())
                        {
                            _current = _selector(_enumerator.Current);
                            return true;
                        }
 
                        Dispose();
                        break;
                }
 
                return false;
            }
 
            public override TResult[] ToArray()
            {
                TResult[] array = new TResult[_source.Count];
                for (int i = 0; i < array.Length; i++)
                {
                    array[i] = _selector(_source[i]);
                }
                return array;
            }
 
            public override List<TResult> ToList()
            {
                List<TResult> list = new List<TResult>(_source.Count);
                for (int i = 0; i < list.Count; i++)
                {
                    list.Add(_selector(_source[i]));
                }
                return list;
            }
 
            private protected override Iterator<TResult> Clone()
                => new SizeOptIListSelectIterator<TSource, TResult>(_source, _selector);
        }
    }
}