diff options
author | Ahson Khan <ahkha@microsoft.com> | 2018-02-02 19:30:25 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-02-02 19:30:25 -0800 |
commit | 4456cc99ba0fbe3c02be3a9f54c34282caeb7218 (patch) | |
tree | ba670df7ce6a071a406a296e3a534bad35dd2276 /src | |
parent | 94ab205d5545699a49cc54d72e9d3d07a454f10a (diff) | |
download | coreclr-4456cc99ba0fbe3c02be3a9f54c34282caeb7218.tar.gz coreclr-4456cc99ba0fbe3c02be3a9f54c34282caeb7218.tar.bz2 coreclr-4456cc99ba0fbe3c02be3a9f54c34282caeb7218.zip |
Changing Span/Memory to return default on null instead of throwing. (#16186)
* Additional changes based on feedback (bounds checks)
* Adding remaining bounds checks
Diffstat (limited to 'src')
-rw-r--r-- | src/mscorlib/shared/System/Memory.cs | 20 | ||||
-rw-r--r-- | src/mscorlib/shared/System/ReadOnlyMemory.cs | 20 | ||||
-rw-r--r-- | src/mscorlib/shared/System/ReadOnlySpan.Fast.cs | 16 | ||||
-rw-r--r-- | src/mscorlib/shared/System/ReadOnlySpan.cs | 14 | ||||
-rw-r--r-- | src/mscorlib/shared/System/Span.Fast.cs | 16 | ||||
-rw-r--r-- | src/mscorlib/shared/System/Span.NonGeneric.cs | 55 | ||||
-rw-r--r-- | src/mscorlib/shared/System/Span.cs | 14 |
7 files changed, 98 insertions, 57 deletions
diff --git a/src/mscorlib/shared/System/Memory.cs b/src/mscorlib/shared/System/Memory.cs index 4df630f764..8fc5b04ee4 100644 --- a/src/mscorlib/shared/System/Memory.cs +++ b/src/mscorlib/shared/System/Memory.cs @@ -40,14 +40,16 @@ namespace System /// Creates a new memory over the entirety of the target array. /// </summary> /// <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> + /// <remarks>Returns default when <paramref name="array"/> is null.</remarks> /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception> [MethodImpl(MethodImplOptions.AggressiveInlining)] public Memory(T[] array) { if (array == null) - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + { + this = default; + return; // returns default + } if (default(T) == null && array.GetType() != typeof(T[])) ThrowHelper.ThrowArrayTypeMismatchException(); @@ -63,8 +65,7 @@ namespace System /// <param name="array">The target array.</param> /// <param name="start">The index at which to begin the memory.</param> /// <param name="length">The number of items in the memory.</param> - /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="array"/> is a null - /// reference (Nothing in Visual Basic).</exception> + /// <remarks>Returns default when <paramref name="array"/> is null.</remarks> /// <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 (<0 or >=Length). @@ -73,7 +74,12 @@ namespace System public Memory(T[] array, int start, int length) { if (array == null) - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + { + if (start != 0 || length != 0) + ThrowHelper.ThrowArgumentOutOfRangeException(); + this = default; + return; // returns default + } if (default(T) == null && array.GetType() != typeof(T[])) ThrowHelper.ThrowArrayTypeMismatchException(); if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start)) @@ -106,7 +112,7 @@ namespace System /// <summary> /// Defines an implicit conversion of an array to a <see cref="Memory{T}"/> /// </summary> - public static implicit operator Memory<T>(T[] array) => (array != null) ? new Memory<T>(array) : default; + public static implicit operator Memory<T>(T[] array) => new Memory<T>(array); /// <summary> /// Defines an implicit conversion of a <see cref="ArraySegment{T}"/> to a <see cref="Memory{T}"/> diff --git a/src/mscorlib/shared/System/ReadOnlyMemory.cs b/src/mscorlib/shared/System/ReadOnlyMemory.cs index 5a8a6fcc21..166a204edb 100644 --- a/src/mscorlib/shared/System/ReadOnlyMemory.cs +++ b/src/mscorlib/shared/System/ReadOnlyMemory.cs @@ -38,14 +38,16 @@ namespace System /// Creates a new memory over the entirety of the target array. /// </summary> /// <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> + /// <remarks>Returns default when <paramref name="array"/> is null.</remarks> /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception> [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlyMemory(T[] array) { if (array == null) - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + { + this = default; + return; // returns default + } _object = array; _index = 0; @@ -59,8 +61,7 @@ namespace System /// <param name="array">The target array.</param> /// <param name="start">The index at which to begin the memory.</param> /// <param name="length">The number of items in the memory.</param> - /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="array"/> is a null - /// reference (Nothing in Visual Basic).</exception> + /// <remarks>Returns default when <paramref name="array"/> is null.</remarks> /// <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 (<0 or >=Length). @@ -69,7 +70,12 @@ namespace System public ReadOnlyMemory(T[] array, int start, int length) { if (array == null) - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + { + if (start != 0 || length != 0) + ThrowHelper.ThrowArgumentOutOfRangeException(); + this = default; + return; // returns default + } if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start)) ThrowHelper.ThrowArgumentOutOfRangeException(); @@ -97,7 +103,7 @@ namespace System /// <summary> /// Defines an implicit conversion of an array to a <see cref="ReadOnlyMemory{T}"/> /// </summary> - public static implicit operator ReadOnlyMemory<T>(T[] array) => (array != null) ? new ReadOnlyMemory<T>(array) : default; + public static implicit operator ReadOnlyMemory<T>(T[] array) => new ReadOnlyMemory<T>(array); /// <summary> /// Defines an implicit conversion of a <see cref="ArraySegment{T}"/> to a <see cref="ReadOnlyMemory{T}"/> diff --git a/src/mscorlib/shared/System/ReadOnlySpan.Fast.cs b/src/mscorlib/shared/System/ReadOnlySpan.Fast.cs index 5c627cc166..2a30b2a927 100644 --- a/src/mscorlib/shared/System/ReadOnlySpan.Fast.cs +++ b/src/mscorlib/shared/System/ReadOnlySpan.Fast.cs @@ -39,13 +39,16 @@ namespace System /// Creates a new read-only span over the entirety of the target array. /// </summary> /// <param name="array">The target array.</param> - /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="array"/> is a null + /// <remarks>Returns default when <paramref name="array"/> is null.</remarks> /// reference (Nothing in Visual Basic).</exception> [MethodImpl(MethodImplOptions.AggressiveInlining)] public ReadOnlySpan(T[] array) { if (array == null) - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + { + this = default; + return; // returns default + } _pointer = new ByReference<T>(ref Unsafe.As<byte, T>(ref array.GetRawSzArrayData())); _length = array.Length; @@ -58,7 +61,7 @@ namespace System /// <param name="array">The target array.</param> /// <param name="start">The index at which to begin the read-only span.</param> /// <param name="length">The number of items in the read-only span.</param> - /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="array"/> is a null + /// <remarks>Returns default when <paramref name="array"/> is null.</remarks> /// reference (Nothing in Visual Basic).</exception> /// <exception cref="System.ArgumentOutOfRangeException"> /// Thrown when the specified <paramref name="start"/> or end index is not in the range (<0 or >=Length). @@ -67,7 +70,12 @@ namespace System public ReadOnlySpan(T[] array, int start, int length) { if (array == null) - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + { + if (start != 0 || length != 0) + ThrowHelper.ThrowArgumentOutOfRangeException(); + this = default; + return; // returns default + } if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start)) ThrowHelper.ThrowArgumentOutOfRangeException(); diff --git a/src/mscorlib/shared/System/ReadOnlySpan.cs b/src/mscorlib/shared/System/ReadOnlySpan.cs index f0f022605e..4d747605ad 100644 --- a/src/mscorlib/shared/System/ReadOnlySpan.cs +++ b/src/mscorlib/shared/System/ReadOnlySpan.cs @@ -29,11 +29,11 @@ namespace System #if !FEATURE_PORTABLE_SPAN [NonVersionable] #endif // !FEATURE_PORTABLE_SPAN - get - { - return _length; - } - } + get + { + return _length; + } + } /// <summary> /// Returns true if Length is 0. @@ -83,13 +83,13 @@ namespace System /// <summary> /// Defines an implicit conversion of an array to a <see cref="ReadOnlySpan{T}"/> /// </summary> - public static implicit operator ReadOnlySpan<T>(T[] array) => array != null ? new ReadOnlySpan<T>(array) : default; + public static implicit operator ReadOnlySpan<T>(T[] array) => new ReadOnlySpan<T>(array); /// <summary> /// Defines an implicit conversion of a <see cref="ArraySegment{T}"/> to a <see cref="ReadOnlySpan{T}"/> /// </summary> public static implicit operator ReadOnlySpan<T>(ArraySegment<T> arraySegment) - => arraySegment.Array != null ? new ReadOnlySpan<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count) : default; + => new ReadOnlySpan<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count); /// <summary> /// Returns a 0-length read-only span whose base is the null pointer. diff --git a/src/mscorlib/shared/System/Span.Fast.cs b/src/mscorlib/shared/System/Span.Fast.cs index 1382e3d214..e0d4ec3227 100644 --- a/src/mscorlib/shared/System/Span.Fast.cs +++ b/src/mscorlib/shared/System/Span.Fast.cs @@ -39,14 +39,17 @@ namespace System /// Creates a new span over the entirety of the target array. /// </summary> /// <param name="array">The target array.</param> - /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="array"/> is a null + /// <remarks>Returns default when <paramref name="array"/> is null.</remarks> /// reference (Nothing in Visual Basic).</exception> /// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception> [MethodImpl(MethodImplOptions.AggressiveInlining)] public Span(T[] array) { if (array == null) - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + { + this = default; + return; // returns default + } if (default(T) == null && array.GetType() != typeof(T[])) ThrowHelper.ThrowArrayTypeMismatchException(); @@ -61,7 +64,7 @@ namespace System /// <param name="array">The target array.</param> /// <param name="start">The index at which to begin the span.</param> /// <param name="length">The number of items in the span.</param> - /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="array"/> is a null + /// <remarks>Returns default when <paramref name="array"/> is null.</remarks> /// reference (Nothing in Visual Basic).</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"> @@ -71,7 +74,12 @@ namespace System public Span(T[] array, int start, int length) { if (array == null) - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array); + { + if (start != 0 || length != 0) + ThrowHelper.ThrowArgumentOutOfRangeException(); + this = default; + return; // returns default + } if (default(T) == null && array.GetType() != typeof(T[])) ThrowHelper.ThrowArrayTypeMismatchException(); if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start)) diff --git a/src/mscorlib/shared/System/Span.NonGeneric.cs b/src/mscorlib/shared/System/Span.NonGeneric.cs index 9ce6acdff6..679e639c58 100644 --- a/src/mscorlib/shared/System/Span.NonGeneric.cs +++ b/src/mscorlib/shared/System/Span.NonGeneric.cs @@ -24,25 +24,29 @@ namespace System { /// <summary>Creates a new <see cref="ReadOnlyMemory{char}"/> over the portion of the target string.</summary> /// <param name="text">The target string.</param> - /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="text"/> is a null reference (Nothing in Visual Basic).</exception> + /// <remarks>Returns default when <paramref name="text"/> is null.</remarks> public static ReadOnlyMemory<char> AsReadOnlyMemory(this string text) { if (text == null) - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.text); + return default; return new ReadOnlyMemory<char>(text, 0, text.Length); } /// <summary>Creates a new <see cref="ReadOnlyMemory{char}"/> over the portion of the target string.</summary> /// <param name="text">The target string.</param> - /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="text"/> is a null reference (Nothing in Visual Basic).</exception> + /// <remarks>Returns default when <paramref name="text"/> is null.</remarks> /// <exception cref="System.ArgumentOutOfRangeException"> /// Thrown when the specified <paramref name="start"/> index is not in range (<0 or >text.Length). /// </exception> public static ReadOnlyMemory<char> AsReadOnlyMemory(this string text, int start) { if (text == null) - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.text); + { + if (start != 0) + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start); + return default; + } if ((uint)start > (uint)text.Length) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start); @@ -52,14 +56,18 @@ namespace System /// <summary>Creates a new <see cref="ReadOnlyMemory{char}"/> over the portion of the target string.</summary> /// <param name="text">The target string.</param> - /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="text"/> is a null reference (Nothing in Visual Basic).</exception> + /// <remarks>Returns default when <paramref name="text"/> is null.</remarks> /// <exception cref="System.ArgumentOutOfRangeException"> /// Thrown when the specified <paramref name="start"/> index or <paramref name="length"/> is not in range. /// </exception> public static ReadOnlyMemory<char> AsReadOnlyMemory(this string text, int start, int length) { if (text == null) - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.text); + { + if (start != 0 || length != 0) + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start); + return default; + } if ((uint)start > (uint)text.Length || (uint)length > (uint)(text.Length - start)) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start); @@ -135,13 +143,13 @@ namespace System /// Creates a new readonly span over the portion of the target string. /// </summary> /// <param name="text">The target string.</param> - /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="text"/> is a null + /// <remarks>Returns default when <paramref name="text"/> is null.</remarks> /// reference (Nothing in Visual Basic).</exception> [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlySpan<char> AsReadOnlySpan(this string text) { if (text == null) - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.text); + return default; return new ReadOnlySpan<char>(ref text.GetRawStringData(), text.Length); } @@ -150,9 +158,7 @@ namespace System /// Creates a new readonly span over the portion of the target string. /// </summary> /// <param name="text">The target string.</param> - /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="text"/> is a null - /// reference (Nothing in Visual Basic). - /// </exception> + /// <remarks>Returns default when <paramref name="text"/> is null.</remarks> /// <exception cref="System.ArgumentOutOfRangeException"> /// Thrown when the specified <paramref name="start"/> index is not in range (<0 or >text.Length). /// </exception> @@ -160,7 +166,11 @@ namespace System public static ReadOnlySpan<char> AsReadOnlySpan(this string text, int start) { if (text == null) - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.text); + { + if (start != 0) + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start); + return default; + } if ((uint)start > (uint)text.Length) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start); @@ -172,9 +182,7 @@ namespace System /// Creates a new readonly span over the portion of the target string. /// </summary> /// <param name="text">The target string.</param> - /// <exception cref="System.ArgumentNullException">Thrown when <paramref name="text"/> is a null - /// reference (Nothing in Visual Basic). - /// </exception> + /// <remarks>Returns default when <paramref name="text"/> is null.</remarks> /// <exception cref="System.ArgumentOutOfRangeException"> /// Thrown when the specified <paramref name="start"/> index or <paramref name="length"/> is not in range. /// </exception> @@ -182,21 +190,26 @@ namespace System public static ReadOnlySpan<char> AsReadOnlySpan(this string text, int start, int length) { if (text == null) - ThrowHelper.ThrowArgumentNullException(ExceptionArgument.text); + { + if (start != 0 || length != 0) + ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start); + return default; + } if ((uint)start > (uint)text.Length || (uint)length > (uint)(text.Length - start)) ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.start); return new ReadOnlySpan<char>(ref Unsafe.Add(ref text.GetRawStringData(), start), length); } - + internal static unsafe void ClearWithoutReferences(ref byte b, nuint byteLength) { if (byteLength == 0) return; - + #if CORECLR && (AMD64 || ARM64) - if (byteLength > 4096) goto PInvoke; + if (byteLength > 4096) + goto PInvoke; Unsafe.InitBlockUnaligned(ref b, 0, (uint)byteLength); return; #else @@ -503,8 +516,8 @@ namespace System return; #endif - - PInvoke: + + PInvoke: RuntimeImports.RhZeroMemory(ref b, byteLength); } diff --git a/src/mscorlib/shared/System/Span.cs b/src/mscorlib/shared/System/Span.cs index f5918110dd..106c0f7d5d 100644 --- a/src/mscorlib/shared/System/Span.cs +++ b/src/mscorlib/shared/System/Span.cs @@ -29,11 +29,11 @@ namespace System #if !FEATURE_PORTABLE_SPAN [NonVersionable] #endif // !FEATURE_PORTABLE_SPAN - get - { - return _length; - } - } + get + { + return _length; + } + } /// <summary> /// Returns true if Length is 0. @@ -84,13 +84,13 @@ 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) => array != null ? new Span<T>(array) : default; + 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) - => arraySegment.Array != null ? new Span<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count) : default; + => new Span<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count); /// <summary> /// Returns an empty <see cref="Span{T}"/> |