61af717836a56ed217eb1b4b4e3950c31ac421ce
[platform/upstream/coreclr.git] / src / System.Private.CoreLib / shared / System / ReadOnlySpan.cs
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5 using System.ComponentModel;
6 using System.Diagnostics;
7 using System.Runtime.CompilerServices;
8
9 using System.Runtime.Versioning;
10
11 #pragma warning disable 0809  //warning CS0809: Obsolete member 'Span<T>.Equals(object)' overrides non-obsolete member 'object.Equals(object)'
12
13 namespace System
14 {
15     /// <summary>
16     /// ReadOnlySpan represents a contiguous region of arbitrary memory. Unlike arrays, it can point to either managed
17     /// or native memory, or to memory allocated on the stack. It is type- and memory-safe.
18     /// </summary>
19     [DebuggerTypeProxy(typeof(SpanDebugView<>))]
20     [DebuggerDisplay("{ToString(),raw}")]
21     public readonly ref partial struct ReadOnlySpan<T>
22     {
23         /// <summary>
24         /// The number of items in the read-only span.
25         /// </summary>
26         public int Length
27         {
28             [NonVersionable]
29             get
30             {
31                 return _length;
32             }
33         }
34
35         /// <summary>
36         /// Returns true if Length is 0.
37         /// </summary>
38         public bool IsEmpty
39         {
40             [NonVersionable]
41             get
42             {
43                 return _length == 0;
44             }
45         }
46         /// <summary>
47         /// Returns false if left and right point at the same memory and have the same length.  Note that
48         /// this does *not* check to see if the *contents* are equal.
49         /// </summary>
50         public static bool operator !=(ReadOnlySpan<T> left, ReadOnlySpan<T> right) => !(left == right);
51
52         /// <summary>
53         /// This method is not supported as spans cannot be boxed. To compare two spans, use operator==.
54         /// <exception cref="System.NotSupportedException">
55         /// Always thrown by this method.
56         /// </exception>
57         /// </summary>
58         [Obsolete("Equals() on ReadOnlySpan will always throw an exception. Use == instead.")]
59         [EditorBrowsable(EditorBrowsableState.Never)]
60         public override bool Equals(object obj)
61         {
62             throw new NotSupportedException(SR.NotSupported_CannotCallEqualsOnSpan);
63         }
64
65         /// <summary>
66         /// This method is not supported as spans cannot be boxed.
67         /// <exception cref="System.NotSupportedException">
68         /// Always thrown by this method.
69         /// </exception>
70         /// </summary>
71         [Obsolete("GetHashCode() on ReadOnlySpan will always throw an exception.")]
72         [EditorBrowsable(EditorBrowsableState.Never)]
73         public override int GetHashCode()
74         {
75             throw new NotSupportedException(SR.NotSupported_CannotCallGetHashCodeOnSpan);
76         }
77
78         /// <summary>
79         /// Defines an implicit conversion of an array to a <see cref="ReadOnlySpan{T}"/>
80         /// </summary>
81         public static implicit operator ReadOnlySpan<T>(T[] array) => new ReadOnlySpan<T>(array);
82
83         /// <summary>
84         /// Defines an implicit conversion of a <see cref="ArraySegment{T}"/> to a <see cref="ReadOnlySpan{T}"/>
85         /// </summary>
86         public static implicit operator ReadOnlySpan<T>(ArraySegment<T> segment)
87             => new ReadOnlySpan<T>(segment.Array, segment.Offset, segment.Count);
88
89         /// <summary>
90         /// Returns a 0-length read-only span whose base is the null pointer.
91         /// </summary>
92         public static ReadOnlySpan<T> Empty => default;
93
94         /// <summary>Gets an enumerator for this span.</summary>
95         public Enumerator GetEnumerator() => new Enumerator(this);
96
97         /// <summary>Enumerates the elements of a <see cref="ReadOnlySpan{T}"/>.</summary>
98         public ref struct Enumerator
99         {
100             /// <summary>The span being enumerated.</summary>
101             private readonly ReadOnlySpan<T> _span;
102             /// <summary>The next index to yield.</summary>
103             private int _index;
104
105             /// <summary>Initialize the enumerator.</summary>
106             /// <param name="span">The span to enumerate.</param>
107             [MethodImpl(MethodImplOptions.AggressiveInlining)]
108             internal Enumerator(ReadOnlySpan<T> span)
109             {
110                 _span = span;
111                 _index = -1;
112             }
113
114             /// <summary>Advances the enumerator to the next element of the span.</summary>
115             [MethodImpl(MethodImplOptions.AggressiveInlining)]
116             public bool MoveNext()
117             {
118                 int index = _index + 1;
119                 if (index < _span.Length)
120                 {
121                     _index = index;
122                     return true;
123                 }
124
125                 return false;
126             }
127
128             /// <summary>Gets the element at the current position of the enumerator.</summary>
129             public ref readonly T Current
130             {
131                 [MethodImpl(MethodImplOptions.AggressiveInlining)]
132                 get => ref _span[_index];
133             }
134         }
135     }
136 }