diff --git a/src/mscorlib/model.xml b/src/mscorlib/model.xml
index 104fc6e5ede3..afc6af1f4c7d 100644
--- a/src/mscorlib/model.xml
+++ b/src/mscorlib/model.xml
@@ -12424,6 +12424,7 @@
+
@@ -12434,8 +12435,8 @@
-
+
@@ -12449,6 +12450,8 @@
+
+
@@ -12456,8 +12459,11 @@
-
+
+
+
+
diff --git a/src/mscorlib/src/System/ReadOnlySpan.cs b/src/mscorlib/src/System/ReadOnlySpan.cs
index 9235fcfa74dc..762a39b65183 100644
--- a/src/mscorlib/src/System/ReadOnlySpan.cs
+++ b/src/mscorlib/src/System/ReadOnlySpan.cs
@@ -6,6 +6,8 @@
using System.Diagnostics;
using System.Runtime.CompilerServices;
+#pragma warning disable 0809 //warning CS0809: Obsolete member 'Span.Equals(object)' overrides non-obsolete member 'object.Equals(object)'
+
namespace System
{
///
@@ -124,6 +126,58 @@ public ref T DangerousGetPinnableReference()
return ref _pointer.Value;
}
+ ///
+ /// This method is not supported as spans cannot be boxed. To compare two spans, use operator==.
+ ///
+ /// Always thrown by this method.
+ ///
+ ///
+ [Obsolete("Equals() on Span will always throw an exception. Use == instead.")]
+ public override bool Equals(object obj)
+ {
+ ThrowHelper.ThrowNotSupportedException_CannotCallEqualsOnSpan();
+ // Prevent compiler error CS0161: 'Span.Equals(object)': not all code paths return a value
+ return default(bool);
+ }
+
+ ///
+ /// This method is not supported as spans cannot be boxed.
+ ///
+ /// Always thrown by this method.
+ ///
+ ///
+ [Obsolete("GetHashCode() on Span will always throw an exception.")]
+ public override int GetHashCode()
+ {
+ ThrowHelper.ThrowNotSupportedException_CannotCallGetHashCodeOnSpan();
+ // Prevent compiler error CS0161: 'Span.GetHashCode()': not all code paths return a value
+ return default(int);
+ }
+
+ ///
+ /// Create a new read-only span over a portion of a regular managed object. This can be useful
+ /// if part of a managed object represents a "fixed array." This is dangerous because
+ /// "length" is not checked, nor is the fact that "rawPointer" actually lies within the object.
+ ///
+ /// The managed object that contains the data to span over.
+ /// A reference to data within that object.
+ /// The number of elements the memory contains.
+ ///
+ /// Thrown when the specified object is null.
+ ///
+ ///
+ /// Thrown when the specified is negative.
+ ///
+ public static ReadOnlySpan DangerousCreate(object obj, ref T objectData, int length)
+ {
+ if (obj == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.obj);
+ if (length < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
+
+ return new ReadOnlySpan(ref objectData, length);
+ }
+
///
/// Defines an implicit conversion of a to a
///
@@ -238,13 +292,19 @@ public ReadOnlySpan Slice(int start, int length)
}
///
- /// Checks to see if two spans point at the same memory. Note that
- /// this does *not* check to see if the *contents* are equal.
+ /// Copies the contents of this read-only span into destination span. If the source
+ /// and destinations overlap, this method behaves as if the original values in
+ /// a temporary location before the destination is overwritten.
+ ///
+ /// The span to copy items into.
+ ///
+ /// Thrown when the destination Span is shorter than the source Span.
+ ///
///
- public bool Equals(ReadOnlySpan other)
+ public void CopyTo(Span destination)
{
- return (_length == other.Length) &&
- (_length == 0 || Unsafe.AreSame(ref DangerousGetPinnableReference(), ref other.DangerousGetPinnableReference()));
+ if (!TryCopyTo(destination))
+ ThrowHelper.ThrowArgumentException_DestinationTooShort();
}
///
@@ -260,6 +320,21 @@ public bool TryCopyTo(Span destination)
SpanHelper.CopyTo(ref destination.DangerousGetPinnableReference(), ref DangerousGetPinnableReference(), _length);
return true;
}
+
+ ///
+ /// Returns true 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)
+ {
+ return left._length == right._length && Unsafe.AreSame(ref left.DangerousGetPinnableReference(), ref right.DangerousGetPinnableReference());
+ }
+
+ ///
+ /// 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);
}
public static class ReadOnlySpanExtensions
diff --git a/src/mscorlib/src/System/Span.cs b/src/mscorlib/src/System/Span.cs
index f1d57d390b12..17d41116e0cd 100644
--- a/src/mscorlib/src/System/Span.cs
+++ b/src/mscorlib/src/System/Span.cs
@@ -123,6 +123,31 @@ public unsafe Span(void* pointer, int length)
_length = length;
}
+ ///
+ /// Create a new span over a portion of a regular managed object. This can be useful
+ /// if part of a managed object represents a "fixed array." This is dangerous because
+ /// "length" is not checked, nor is the fact that "rawPointer" actually lies within the object.
+ ///
+ /// The managed object that contains the data to span over.
+ /// A reference to data within that object.
+ /// The number of elements the memory contains.
+ ///
+ /// Thrown when the specified object is null.
+ ///
+ ///
+ /// Thrown when the specified is negative.
+ ///
+ public static Span DangerousCreate(object obj, ref T objectData, int length)
+ {
+ if (obj == null)
+ ThrowHelper.ThrowArgumentNullException(ExceptionArgument.obj);
+ if (length < 0)
+ ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
+
+ return new Span(ref objectData, length);
+ }
+
+
///
/// An internal helper for creating spans.
///
@@ -211,23 +236,16 @@ public bool TryCopyTo(Span destination)
/// Returns true 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 ==(Span left, Span right) => left.Equals(right);
+ public static bool operator ==(Span left, Span right)
+ {
+ return left._length == right._length && Unsafe.AreSame(ref left.DangerousGetPinnableReference(), ref right.DangerousGetPinnableReference());
+ }
///
/// 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 !=(Span left, Span right) => !left.Equals(right);
-
- ///
- /// Checks to see if two spans point at the same memory. Note that
- /// this does *not* check to see if the *contents* are equal.
- ///
- public bool Equals(Span other)
- {
- return (_length == other.Length) &&
- (_length == 0 || Unsafe.AreSame(ref DangerousGetPinnableReference(), ref other.DangerousGetPinnableReference()));
- }
+ public static bool operator !=(Span left, Span right) => !(left == right);
///
/// This method is not supported as spans cannot be boxed. To compare two spans, use operator==.
@@ -267,6 +285,11 @@ public override int GetHashCode()
///
public static implicit operator Span(ArraySegment arraySegment) => new Span(arraySegment.Array, arraySegment.Offset, arraySegment.Count);
+ ///
+ /// Defines an implicit conversion of a to a
+ ///
+ public static implicit operator ReadOnlySpan(Span span) => new ReadOnlySpan(ref span.DangerousGetPinnableReference(), span._length);
+
///
/// Forms a slice out of the given span, beginning at 'start'.
///