summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Warren <matt.warren@live.co.uk>2016-12-12 17:30:58 +0000
committerJan Kotas <jkotas@microsoft.com>2016-12-12 09:30:58 -0800
commit98798b78e2e3284409289c7253bac7b999c0ad88 (patch)
treee363f2f1d5516cb36f3920c531b67ad3a1efe2ff
parent5dbaa3cb2e2e11d98924afe9de472469b5136885 (diff)
downloadcoreclr-98798b78e2e3284409289c7253bac7b999c0ad88.tar.gz
coreclr-98798b78e2e3284409289c7253bac7b999c0ad88.tar.bz2
coreclr-98798b78e2e3284409289c7253bac7b999c0ad88.zip
Span<T> api update (#8583)
* Changing method/property order to match CoreFX impl To make diffing the files easier * Added other missing methods to match CoreFX impl Added: - public void CopyTo(Span<T> destination) - public static bool operator ==(Span<T> left, Span<T> right) - public static bool operator !=(Span<T> left, Span<T> right) - public override bool Equals(object obj) - public override int GetHashCode() Also removed 'public void Set(ReadOnlySpan<T> values)' and it's no longer part of the Span<T> public API, see https://github.com/dotnet/apireviews/tree/master/2016/11-04-SpanOfT#spantset
-rw-r--r--src/mscorlib/model.xml6
-rw-r--r--src/mscorlib/src/System.Private.CoreLib.txt5
-rw-r--r--src/mscorlib/src/System/Span.cs182
-rw-r--r--src/mscorlib/src/System/ThrowHelper.cs12
4 files changed, 130 insertions, 75 deletions
diff --git a/src/mscorlib/model.xml b/src/mscorlib/model.xml
index c221d6c878..64901a2207 100644
--- a/src/mscorlib/model.xml
+++ b/src/mscorlib/model.xml
@@ -12422,6 +12422,8 @@
<Member Name="DangerousGetPinnableReference" />
<Member Name="op_Implicit(T[])" ReturnType="System.Span&lt;T&gt;" />
<Member Name="op_Implicit(System.ArraySegment&lt;T&gt;)" ReturnType="System.Span&lt;T&gt;" />
+ <Member Name="op_Equality(System.Span&lt;T&gt;,System.Span&lt;T&gt;)" />
+ <Member Name="op_Inequality(System.Span&lt;T&gt;,System.Span&lt;T&gt;)" />
<Member Name="get_Length" />
<Member Name="get_Empty" />
<Member Name="get_IsEmpty" />
@@ -12431,8 +12433,10 @@
<Member Name="Slice(System.Int32)" />
<Member Name="Slice(System.Int32,System.Int32)" />
<Member Name="Equals(System.Span&lt;T&gt;)" />
+ <Member Name="Equals(System.Object)" />
+ <Member Name="GetHashCode" />
+ <Member Name="CopyTo(System.Span&lt;T&gt;)" />
<Member Name="TryCopyTo(System.Span&lt;T&gt;)" />
- <Member Name="Set(System.ReadOnlySpan&lt;T&gt;)" />
</Type>
<Type Name="System.ReadOnlySpan&lt;T&gt;" Condition="FEATURE_SPAN_OF_T">
<Member Name="#ctor(T[])" />
diff --git a/src/mscorlib/src/System.Private.CoreLib.txt b/src/mscorlib/src/System.Private.CoreLib.txt
index ee1a962c87..cf17dae96f 100644
--- a/src/mscorlib/src/System.Private.CoreLib.txt
+++ b/src/mscorlib/src/System.Private.CoreLib.txt
@@ -592,6 +592,7 @@ Argument_NativeOverlappedAlreadyFree = 'overlapped' has already been freed.
Argument_AlreadyBoundOrSyncHandle = 'handle' has already been bound to the thread pool, or was not opened for asynchronous I/O.
#if FEATURE_SPAN_OF_T
Argument_InvalidTypeWithPointersNotSupported = Cannot use type '{0}'. Only value types without pointers or references are supported.
+Argument_DestinationTooShort = Destination is too short.
#endif // FEATURE_SPAN_OF_T
;
@@ -1431,6 +1432,10 @@ NotSupported_WindowsPhone = {0} is not supported.
NotSupported_AssemblyLoadCodeBase = Assembly.Load with a Codebase is not supported.
NotSupported_AssemblyLoadFromHash = Assembly.LoadFrom with hashValue is not supported.
#endif
+#if FEATURE_SPAN_OF_T
+NotSupported_CannotCallEqualsOnSpan = Equals() on Span and ReadOnlySpan is not supported. Use operator== instead.
+NotSupported_CannotCallGetHashCodeOnSpan = GetHashCode() on Span and ReadOnlySpan is not supported.
+#endif // FEATURE_SPAN_OF_T
; TypeLoadException
TypeLoad_ResolveType = Could not resolve type '{0}'.
diff --git a/src/mscorlib/src/System/Span.cs b/src/mscorlib/src/System/Span.cs
index 21785cd865..f1d57d390b 100644
--- a/src/mscorlib/src/System/Span.cs
+++ b/src/mscorlib/src/System/Span.cs
@@ -6,6 +6,8 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
+#pragma warning disable 0809 //warning CS0809: Obsolete member 'Span<T>.Equals(object)' overrides non-obsolete member 'object.Equals(object)'
+
namespace System
{
/// <summary>
@@ -26,7 +28,7 @@ namespace System
/// <param name="array">The target array.</param>
/// <exception cref="System.ArgumentNullException">Thrown when <paramref name="array"/> is a null
/// reference (Nothing in Visual Basic).</exception>
- /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant.</exception>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception>
public Span(T[] array)
{
if (array == null)
@@ -48,7 +50,7 @@ namespace System
/// <param name="start">The index at which to begin the span.</param>
/// <exception cref="System.ArgumentNullException">Thrown when <paramref name="array"/> is a null
/// reference (Nothing in Visual Basic).</exception>
- /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant.</exception>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// Thrown when the specified <paramref name="start"/> is not in the range (&lt;0 or &gt;=Length).
/// </exception>
@@ -76,7 +78,7 @@ namespace System
/// <param name="length">The number of items in the span.</param>
/// <exception cref="System.ArgumentNullException">Thrown when <paramref name="array"/> is a null
/// reference (Nothing in Visual Basic).</exception>
- /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant.</exception>
+ /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception>
/// <exception cref="System.ArgumentOutOfRangeException">
/// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=Length).
/// </exception>
@@ -101,7 +103,7 @@ namespace System
/// out of a void*-typed block of memory. And the length is not checked.
/// But if this creation is correct, then all subsequent uses are correct.
/// </summary>
- /// <param name="ptr">An unmanaged pointer to memory.</param>
+ /// <param name="pointer">An unmanaged pointer to memory.</param>
/// <param name="length">The number of <typeparamref name="T"/> elements the memory contains.</param>
/// <exception cref="System.ArgumentException">
/// Thrown when <typeparamref name="T"/> is reference type or contains pointers and hence cannot be stored in unmanaged memory.
@@ -140,44 +142,14 @@ namespace System
}
/// <summary>
- /// Defines an implicit conversion of an array to a <see cref="Span{T}"/>
- /// </summary>
- public static implicit operator Span<T>(T[] array)
- {
- return new Span<T>(array);
- }
-
- /// <summary>
- /// Defines an implicit conversion of a <see cref="ArraySegment{T}"/> to a <see cref="Span{T}"/>
- /// </summary>
- public static implicit operator Span<T>(ArraySegment<T> arraySegment)
- {
- return new Span<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count);
- }
-
- /// <summary>
/// Gets the number of elements contained in the <see cref="Span{T}"/>
/// </summary>
- public int Length
- {
- get { return _length; }
- }
-
- /// <summary>
- /// Returns an empty <see cref="Span{T}"/>
- /// </summary>
- public static Span<T> Empty
- {
- get { return default(Span<T>); }
- }
+ public int Length => _length;
/// <summary>
/// Returns whether the <see cref="Span{T}"/> is empty.
/// </summary>
- public bool IsEmpty
- {
- get { return _length == 0; }
- }
+ public bool IsEmpty => _length == 0;
/// <summary>
/// Fetches the element at the specified index.
@@ -204,21 +176,98 @@ namespace System
}
/// <summary>
- /// Copies the contents of this span into a new array. This heap
- /// allocates, so should generally be avoided, however is sometimes
- /// necessary to bridge the gap with APIs written in terms of arrays.
+ /// Copies the contents of this 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.
/// </summary>
- public T[] ToArray()
+ /// <param name="destination">The span to copy items into.</param>
+ /// <exception cref="System.ArgumentException">
+ /// Thrown when the destination Span is shorter than the source Span.
+ /// </exception>
+ public void CopyTo(Span<T> destination)
{
- if (_length == 0)
- return Array.Empty<T>();
+ if (!TryCopyTo(destination))
+ ThrowHelper.ThrowArgumentException_DestinationTooShort();
+ }
- var destination = new T[_length];
- SpanHelper.CopyTo<T>(ref JitHelpers.GetArrayData(destination), ref DangerousGetPinnableReference(), _length);
- return destination;
+ /// <summary>
+ /// Copies the contents of this 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.
+ /// </summary>
+ /// <param name="destination">The span to copy items into.</param>
+ /// <returns>If the destination span is shorter than the source span, this method
+ /// return false and no data is written to the destination.</returns>
+ public bool TryCopyTo(Span<T> destination)
+ {
+ if ((uint)_length > (uint)destination.Length)
+ return false;
+
+ SpanHelper.CopyTo<T>(ref destination.DangerousGetPinnableReference(), ref DangerousGetPinnableReference(), _length);
+ return true;
}
/// <summary>
+ /// 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.
+ /// </summary>
+ public static bool operator ==(Span<T> left, Span<T> right) => left.Equals(right);
+
+ /// <summary>
+ /// 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.
+ /// </summary>
+ public static bool operator !=(Span<T> left, Span<T> right) => !left.Equals(right);
+
+ /// <summary>
+ /// Checks to see if two spans point at the same memory. Note that
+ /// this does *not* check to see if the *contents* are equal.
+ /// </summary>
+ public bool Equals(Span<T> other)
+ {
+ return (_length == other.Length) &&
+ (_length == 0 || Unsafe.AreSame(ref DangerousGetPinnableReference(), ref other.DangerousGetPinnableReference()));
+ }
+
+ /// <summary>
+ /// This method is not supported as spans cannot be boxed. To compare two spans, use operator==.
+ /// <exception cref="System.NotSupportedException">
+ /// Always thrown by this method.
+ /// </exception>
+ /// </summary>
+ [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<T>.Equals(object)': not all code paths return a value
+ return default(bool);
+ }
+
+ /// <summary>
+ /// This method is not supported as spans cannot be boxed.
+ /// <exception cref="System.NotSupportedException">
+ /// Always thrown by this method.
+ /// </exception>
+ /// </summary>
+ [Obsolete("GetHashCode() on Span will always throw an exception.")]
+ public override int GetHashCode()
+ {
+ ThrowHelper.ThrowNotSupportedException_CannotCallGetHashCodeOnSpan();
+ // Prevent compiler error CS0161: 'Span<T>.GetHashCode()': not all code paths return a value
+ return default(int);
+ }
+
+ /// <summary>
+ /// Defines an implicit conversion of an array to a <see cref="Span{T}"/>
+ /// </summary>
+ public static implicit operator Span<T>(T[] array) => new Span<T>(array);
+
+ /// <summary>
+ /// Defines an implicit conversion of a <see cref="ArraySegment{T}"/> to a <see cref="Span{T}"/>
+ /// </summary>
+ public static implicit operator Span<T>(ArraySegment<T> arraySegment) => new Span<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count);
+
+ /// <summary>
/// Forms a slice out of the given span, beginning at 'start'.
/// </summary>
/// <param name="start">The index at which to begin this slice.</param>
@@ -238,7 +287,7 @@ namespace System
/// Forms a slice out of the given span, beginning at 'start', of given length
/// </summary>
/// <param name="start">The index at which to begin this slice.</param>
- /// <param name="end">The index at which to end this slice (exclusive).</param>
+ /// <param name="length">The desired length for the slice (exclusive).</param>
/// <exception cref="System.ArgumentOutOfRangeException">
/// Thrown when the specified <paramref name="start"/> or end index is not in range (&lt;0 or &gt;&eq;Length).
/// </exception>
@@ -252,39 +301,24 @@ namespace System
}
/// <summary>
- /// Checks to see if two spans point at the same memory. Note that
- /// this does *not* check to see if the *contents* are equal.
- /// </summary>
- public bool Equals(Span<T> other)
- {
- return (_length == other.Length) &&
- (_length == 0 || Unsafe.AreSame(ref DangerousGetPinnableReference(), ref other.DangerousGetPinnableReference()));
- }
-
- /// <summary>
- /// Copies the contents of this span into destination span. The destination
- /// must be at least as big as the source, and may be bigger.
+ /// Copies the contents of this span into a new array. This heap
+ /// allocates, so should generally be avoided, however it is sometimes
+ /// necessary to bridge the gap with APIs written in terms of arrays.
/// </summary>
- /// <param name="destination">The span to copy items into.</param>
- public bool TryCopyTo(Span<T> destination)
+ public T[] ToArray()
{
- if ((uint)_length > (uint)destination.Length)
- return false;
+ if (_length == 0)
+ return Array.Empty<T>();
- SpanHelper.CopyTo<T>(ref destination.DangerousGetPinnableReference(), ref DangerousGetPinnableReference(), _length);
- return true;
+ var destination = new T[_length];
+ SpanHelper.CopyTo<T>(ref JitHelpers.GetArrayData(destination), ref DangerousGetPinnableReference(), _length);
+ return destination;
}
- /// <exception cref="System.ArgumentOutOfRangeException">
- /// Thrown when the specified <paramref name="values"/>'s Length is longer than source span's Length.
- /// </exception>
- public void Set(ReadOnlySpan<T> values)
- {
- if ((uint)values.Length > (uint)_length)
- ThrowHelper.ThrowArgumentOutOfRangeException();
-
- SpanHelper.CopyTo<T>(ref DangerousGetPinnableReference(), ref values.DangerousGetPinnableReference(), values.Length);
- }
+ // <summary>
+ /// Returns an empty <see cref="Span{T}"/>
+ /// </summary>
+ public static Span<T> Empty => default(Span<T>);
}
public static class SpanExtensions
diff --git a/src/mscorlib/src/System/ThrowHelper.cs b/src/mscorlib/src/System/ThrowHelper.cs
index be91d7cdbf..74a08cdc8b 100644
--- a/src/mscorlib/src/System/ThrowHelper.cs
+++ b/src/mscorlib/src/System/ThrowHelper.cs
@@ -59,6 +59,18 @@ namespace System {
internal static void ThrowArgumentOutOfRangeException() {
throw new ArgumentOutOfRangeException();
}
+
+ internal static void ThrowArgumentException_DestinationTooShort() {
+ throw new ArgumentException(Environment.GetResourceString("Argument_DestinationTooShort"));
+ }
+
+ internal static void ThrowNotSupportedException_CannotCallEqualsOnSpan() {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_CannotCallEqualsOnSpan"));
+ }
+
+ internal static void ThrowNotSupportedException_CannotCallGetHashCodeOnSpan() {
+ throw new NotSupportedException(Environment.GetResourceString("NotSupported_CannotCallGetHashCodeOnSpan"));
+ }
#endif
internal static void ThrowArgumentOutOfRange_IndexException() {