// 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.ComponentModel; using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.Versioning; #pragma warning disable 0809 //warning CS0809: Obsolete member 'Span.Equals(object)' overrides non-obsolete member 'object.Equals(object)' namespace System { /// /// ReadOnlySpan represents a contiguous region of arbitrary memory. Unlike arrays, it can point to either managed /// or native memory, or to memory allocated on the stack. It is type- and memory-safe. /// [DebuggerTypeProxy(typeof(SpanDebugView<>))] [DebuggerDisplay("{ToString(),raw}")] public readonly ref partial struct ReadOnlySpan { /// /// The number of items in the read-only span. /// public int Length { [NonVersionable] get { return _length; } } /// /// Returns true if Length is 0. /// public bool IsEmpty { [NonVersionable] get { // Workaround for https://github.com/dotnet/coreclr/issues/19620 return 0 >= (uint)_length; } } /// /// Returns false if left and right point at the same memory and have the same length. Note that /// this does *not* check to see if the *contents* are equal. /// public static bool operator !=(ReadOnlySpan left, ReadOnlySpan right) => !(left == right); /// /// This method is not supported as spans cannot be boxed. To compare two spans, use operator==. /// /// Always thrown by this method. /// /// [Obsolete("Equals() on ReadOnlySpan will always throw an exception. Use == instead.")] [EditorBrowsable(EditorBrowsableState.Never)] public override bool Equals(object? obj) { throw new NotSupportedException(SR.NotSupported_CannotCallEqualsOnSpan); } /// /// This method is not supported as spans cannot be boxed. /// /// Always thrown by this method. /// /// [Obsolete("GetHashCode() on ReadOnlySpan will always throw an exception.")] [EditorBrowsable(EditorBrowsableState.Never)] public override int GetHashCode() { throw new NotSupportedException(SR.NotSupported_CannotCallGetHashCodeOnSpan); } /// /// Defines an implicit conversion of an array to a /// public static implicit operator ReadOnlySpan(T[]? array) => new ReadOnlySpan(array); /// /// Defines an implicit conversion of a to a /// public static implicit operator ReadOnlySpan(ArraySegment segment) => new ReadOnlySpan(segment.Array, segment.Offset, segment.Count); /// /// Returns a 0-length read-only span whose base is the null pointer. /// public static ReadOnlySpan Empty => default; /// Gets an enumerator for this span. public Enumerator GetEnumerator() => new Enumerator(this); /// Enumerates the elements of a . public ref struct Enumerator { /// The span being enumerated. private readonly ReadOnlySpan _span; /// The next index to yield. private int _index; /// Initialize the enumerator. /// The span to enumerate. [MethodImpl(MethodImplOptions.AggressiveInlining)] internal Enumerator(ReadOnlySpan span) { _span = span; _index = -1; } /// Advances the enumerator to the next element of the span. [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool MoveNext() { int index = _index + 1; if (index < _span.Length) { _index = index; return true; } return false; } /// Gets the element at the current position of the enumerator. public ref readonly T Current { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => ref _span[_index]; } } } }