diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs index 7798afdff80b3..4e106749c3387 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/Array.NativeAot.cs @@ -1157,38 +1157,6 @@ private static int LastIndexOfImpl(T[] array, T value, int startIndex, int co } } - internal class ArrayEnumeratorBase : ICloneable - { - protected int _index; - protected int _endIndex; - - internal ArrayEnumeratorBase() - { - _index = -1; - } - - public bool MoveNext() - { - if (_index < _endIndex) - { - _index++; - return (_index < _endIndex); - } - return false; - } - - public object Clone() - { - return MemberwiseClone(); - } - -#pragma warning disable CA1822 // https://github.com/dotnet/roslyn-analyzers/issues/5911 - public void Dispose() - { - } -#pragma warning restore CA1822 - } - // // Note: the declared base type and interface list also determines what Reflection returns from TypeInfo.BaseType and TypeInfo.ImplementedInterfaces for array types. // This also means the class must be declared "public" so that the framework can reflect on it. @@ -1200,17 +1168,15 @@ private Array() { } public new IEnumerator GetEnumerator() { - // get length so we don't have to call the Length property again in ArrayEnumerator constructor - // and avoid more checking there too. - int length = this.Length; - return length == 0 ? ArrayEnumerator.Empty : new ArrayEnumerator(Unsafe.As(this), length); + T[] _this = Unsafe.As(this); + return _this.Length == 0 ? SZGenericArrayEnumerator.Empty : new SZGenericArrayEnumerator(_this); } public int Count { get { - return this.Length; + return Unsafe.As(this).Length; } } @@ -1240,13 +1206,14 @@ public void Clear() public bool Contains(T item) { - T[] array = Unsafe.As(this); - return Array.IndexOf(array, item, 0, array.Length) >= 0; + T[] _this = Unsafe.As(this); + return Array.IndexOf(_this, item, 0, _this.Length) >= 0; } public void CopyTo(T[] array, int arrayIndex) { - Array.Copy(Unsafe.As(this), 0, array, arrayIndex, this.Length); + T[] _this = Unsafe.As(this); + Array.Copy(_this, 0, array, arrayIndex, _this.Length); } public bool Remove(T item) @@ -1284,8 +1251,8 @@ public T this[int index] public int IndexOf(T item) { - T[] array = Unsafe.As(this); - return Array.IndexOf(array, item, 0, array.Length); + T[] _this = Unsafe.As(this); + return Array.IndexOf(_this, item, 0, _this.Length); } public void Insert(int index, T item) @@ -1297,43 +1264,6 @@ public void RemoveAt(int index) { ThrowHelper.ThrowNotSupportedException(); } - - private sealed class ArrayEnumerator : ArrayEnumeratorBase, IEnumerator - { - private readonly T[] _array; - - // Passing -1 for endIndex so that MoveNext always returns false without mutating _index - internal static readonly ArrayEnumerator Empty = new ArrayEnumerator(null, -1); - - internal ArrayEnumerator(T[] array, int endIndex) - { - _array = array; - _endIndex = endIndex; - } - - public T Current - { - get - { - if ((uint)_index >= (uint)_endIndex) - ThrowHelper.ThrowInvalidOperationException(); - return _array[_index]; - } - } - - object IEnumerator.Current - { - get - { - return Current; - } - } - - void IEnumerator.Reset() - { - _index = -1; - } - } } public class MDArray diff --git a/src/libraries/System.Private.CoreLib/src/System/Array.Enumerators.cs b/src/libraries/System.Private.CoreLib/src/System/Array.Enumerators.cs index 04c972c0a3c45..8431e98bef527 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Array.Enumerators.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Array.Enumerators.cs @@ -1,8 +1,10 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System; using System.Collections; using System.Collections.Generic; +using System.Runtime.CompilerServices; using System.Diagnostics; namespace System @@ -64,18 +66,12 @@ public void Reset() } } - internal sealed class SZGenericArrayEnumerator : IEnumerator + internal class SZGenericArrayEnumeratorBase { - private readonly T[] _array; - private int _index; + protected readonly Array _array; + protected int _index; - // Array.Empty is intentionally omitted here, since we don't want to pay for generic instantiations that - // wouldn't have otherwise been used. -#pragma warning disable CA1825 - internal static readonly SZGenericArrayEnumerator Empty = new SZGenericArrayEnumerator(new T[0]); -#pragma warning restore CA1825 - - internal SZGenericArrayEnumerator(T[] array) + protected SZGenericArrayEnumeratorBase(Array array) { Debug.Assert(array != null); @@ -86,21 +82,44 @@ internal SZGenericArrayEnumerator(T[] array) public bool MoveNext() { int index = _index + 1; - if ((uint)index >= (uint)_array.Length) + int length = (int)_array.NativeLength; + if ((uint)index >= (uint)length) { - _index = _array.Length; + _index = length; return false; } _index = index; return true; } + public void Reset() => _index = -1; + +#pragma warning disable CA1822 // Mark members as static + public void Dispose() + { + } +#pragma warning restore CA1822 + } + + internal sealed class SZGenericArrayEnumerator : SZGenericArrayEnumeratorBase, IEnumerator + { + // Array.Empty is intentionally omitted here, since we don't want to pay for generic instantiations that + // wouldn't have otherwise been used. +#pragma warning disable CA1825 + internal static readonly SZGenericArrayEnumerator Empty = new SZGenericArrayEnumerator(new T[0]); +#pragma warning restore CA1825 + + public SZGenericArrayEnumerator(T[] array) + : base(array) + { + } + public T Current { get { int index = _index; - T[] array = _array; + T[] array = Unsafe.As(_array); if ((uint)index >= (uint)array.Length) { @@ -112,11 +131,5 @@ public T Current } object? IEnumerator.Current => Current; - - void IEnumerator.Reset() => _index = -1; - - public void Dispose() - { - } } }