Skip to content

Commit 3e2e43e

Browse files
authored
Nullable: Span and friends (dotnet#23734)
1 parent bd05029 commit 3e2e43e

19 files changed

+97
-78
lines changed

src/System.Private.CoreLib/shared/System/ByReference.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
#nullable enable
56
using System.Runtime.CompilerServices;
67
using System.Runtime.Versioning;
78

src/System.Private.CoreLib/shared/System/ISpanFormattable.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
#nullable enable
56
namespace System
67
{
78
internal interface ISpanFormattable
89
{
9-
bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider provider);
10+
bool TryFormat(Span<char> destination, out int charsWritten, ReadOnlySpan<char> format, IFormatProvider? provider);
1011
}
1112
}

src/System.Private.CoreLib/shared/System/Memory.cs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
#nullable enable
56
using System.Buffers;
67
using System.Diagnostics;
78
using System.Runtime.CompilerServices;
@@ -28,7 +29,7 @@ namespace System
2829
// The highest order bit of _index is used to discern whether _object is a pre-pinned array.
2930
// (_index < 0) => _object is a pre-pinned array, so Pin() will not allocate a new GCHandle
3031
// (else) => Pin() needs to allocate a new GCHandle to pin the object.
31-
private readonly object _object;
32+
private readonly object? _object;
3233
private readonly int _index;
3334
private readonly int _length;
3435

@@ -39,14 +40,14 @@ namespace System
3940
/// <remarks>Returns default when <paramref name="array"/> is null.</remarks>
4041
/// <exception cref="System.ArrayTypeMismatchException">Thrown when <paramref name="array"/> is covariant and array's type is not exactly T[].</exception>
4142
[MethodImpl(MethodImplOptions.AggressiveInlining)]
42-
public Memory(T[] array)
43+
public Memory(T[]? array)
4344
{
4445
if (array == null)
4546
{
4647
this = default;
4748
return; // returns default
4849
}
49-
if (default(T) == null && array.GetType() != typeof(T[]))
50+
if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
5051
ThrowHelper.ThrowArrayTypeMismatchException();
5152

5253
_object = array;
@@ -55,7 +56,7 @@ public Memory(T[] array)
5556
}
5657

5758
[MethodImpl(MethodImplOptions.AggressiveInlining)]
58-
internal Memory(T[] array, int start)
59+
internal Memory(T[]? array, int start)
5960
{
6061
if (array == null)
6162
{
@@ -64,7 +65,7 @@ internal Memory(T[] array, int start)
6465
this = default;
6566
return; // returns default
6667
}
67-
if (default(T) == null && array.GetType() != typeof(T[]))
68+
if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
6869
ThrowHelper.ThrowArrayTypeMismatchException();
6970
if ((uint)start > (uint)array.Length)
7071
ThrowHelper.ThrowArgumentOutOfRangeException();
@@ -87,7 +88,7 @@ internal Memory(T[] array, int start)
8788
/// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=Length).
8889
/// </exception>
8990
[MethodImpl(MethodImplOptions.AggressiveInlining)]
90-
public Memory(T[] array, int start, int length)
91+
public Memory(T[]? array, int start, int length)
9192
{
9293
if (array == null)
9394
{
@@ -96,7 +97,7 @@ public Memory(T[] array, int start, int length)
9697
this = default;
9798
return; // returns default
9899
}
99-
if (default(T) == null && array.GetType() != typeof(T[]))
100+
if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
100101
ThrowHelper.ThrowArrayTypeMismatchException();
101102
#if BIT64
102103
// See comment in Span<T>.Slice for how this works.
@@ -160,7 +161,7 @@ internal Memory(MemoryManager<T> manager, int start, int length)
160161
}
161162

162163
[MethodImpl(MethodImplOptions.AggressiveInlining)]
163-
internal Memory(object obj, int start, int length)
164+
internal Memory(object? obj, int start, int length)
164165
{
165166
// No validation performed in release builds; caller must provide any necessary validation.
166167

@@ -181,7 +182,7 @@ internal Memory(object obj, int start, int length)
181182
/// <summary>
182183
/// Defines an implicit conversion of an array to a <see cref="Memory{T}"/>
183184
/// </summary>
184-
public static implicit operator Memory<T>(T[] array) => new Memory<T>(array);
185+
public static implicit operator Memory<T>(T[]? array) => new Memory<T>(array);
185186

186187
/// <summary>
187188
/// Defines an implicit conversion of a <see cref="ArraySegment{T}"/> to a <see cref="Memory{T}"/>
@@ -322,7 +323,7 @@ public unsafe Span<T> Span
322323

323324
// Copy this field into a local so that it can't change out from under us mid-operation.
324325

325-
object tmpObject = _object;
326+
object? tmpObject = _object;
326327
if (tmpObject != null)
327328
{
328329
if (typeof(T) == typeof(char) && tmpObject.GetType() == typeof(string))
@@ -440,7 +441,7 @@ public unsafe MemoryHandle Pin()
440441
// is torn. This is ok since the caller is expecting to use raw pointers,
441442
// and we're not required to keep this as safe as the other Span-based APIs.
442443

443-
object tmpObject = _object;
444+
object? tmpObject = _object;
444445
if (tmpObject != null)
445446
{
446447
if (typeof(T) == typeof(char) && tmpObject is string s)
@@ -497,7 +498,7 @@ public unsafe MemoryHandle Pin()
497498
/// Returns true if the object is Memory or ReadOnlyMemory and if both objects point to the same array and have the same length.
498499
/// </summary>
499500
[EditorBrowsable(EditorBrowsableState.Never)]
500-
public override bool Equals(object obj)
501+
public override bool Equals(object? obj)
501502
{
502503
if (obj is ReadOnlyMemory<T>)
503504
{

src/System.Private.CoreLib/shared/System/MemoryExtensions.Fast.cs

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
#nullable enable
56
using System.Diagnostics;
67
using System.Globalization;
78
using System.Runtime.CompilerServices;
@@ -237,7 +238,7 @@ public static int ToLower(this ReadOnlySpan<char> source, Span<char> destination
237238
if (GlobalizationMode.Invariant)
238239
TextInfo.ToLowerAsciiInvariant(source, destination);
239240
else
240-
culture.TextInfo.ChangeCaseToLower(source, destination);
241+
culture!.TextInfo.ChangeCaseToLower(source, destination); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
241242
return source.Length;
242243
}
243244

@@ -288,7 +289,7 @@ public static int ToUpper(this ReadOnlySpan<char> source, Span<char> destination
288289
if (GlobalizationMode.Invariant)
289290
TextInfo.ToUpperAsciiInvariant(source, destination);
290291
else
291-
culture.TextInfo.ChangeCaseToUpper(source, destination);
292+
culture!.TextInfo.ChangeCaseToUpper(source, destination); // TODO-NULLABLE: https://github.com/dotnet/csharplang/issues/538
292293
return source.Length;
293294
}
294295

@@ -384,15 +385,15 @@ public static bool StartsWith(this ReadOnlySpan<char> span, ReadOnlySpan<char> v
384385
/// Creates a new span over the portion of the target array.
385386
/// </summary>
386387
[MethodImpl(MethodImplOptions.AggressiveInlining)]
387-
public static Span<T> AsSpan<T>(this T[] array, int start)
388+
public static Span<T> AsSpan<T>(this T[]? array, int start)
388389
{
389390
if (array == null)
390391
{
391392
if (start != 0)
392393
ThrowHelper.ThrowArgumentOutOfRangeException();
393394
return default;
394395
}
395-
if (default(T) == null && array.GetType() != typeof(T[]))
396+
if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
396397
ThrowHelper.ThrowArrayTypeMismatchException();
397398
if ((uint)start > (uint)array.Length)
398399
ThrowHelper.ThrowArgumentOutOfRangeException();
@@ -404,7 +405,7 @@ public static Span<T> AsSpan<T>(this T[] array, int start)
404405
/// Creates a new span over the portion of the target array.
405406
/// </summary>
406407
[MethodImpl(MethodImplOptions.AggressiveInlining)]
407-
public static Span<T> AsSpan<T>(this T[] array, Index startIndex)
408+
public static Span<T> AsSpan<T>(this T[]? array, Index startIndex)
408409
{
409410
if (array == null)
410411
{
@@ -414,7 +415,7 @@ public static Span<T> AsSpan<T>(this T[] array, Index startIndex)
414415
return default;
415416
}
416417

417-
if (default(T) == null && array.GetType() != typeof(T[]))
418+
if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
418419
ThrowHelper.ThrowArrayTypeMismatchException();
419420

420421
int actualIndex = startIndex.GetOffset(array.Length);
@@ -428,7 +429,7 @@ public static Span<T> AsSpan<T>(this T[] array, Index startIndex)
428429
/// Creates a new span over the portion of the target array.
429430
/// </summary>
430431
[MethodImpl(MethodImplOptions.AggressiveInlining)]
431-
public static Span<T> AsSpan<T>(this T[] array, Range range)
432+
public static Span<T> AsSpan<T>(this T[]? array, Range range)
432433
{
433434
if (array == null)
434435
{
@@ -441,7 +442,7 @@ public static Span<T> AsSpan<T>(this T[] array, Range range)
441442
return default;
442443
}
443444

444-
if (default(T) == null && array.GetType() != typeof(T[]))
445+
if (default(T)! == null && array.GetType() != typeof(T[])) // TODO-NULLABLE: https://github.com/dotnet/roslyn/issues/34757
445446
ThrowHelper.ThrowArrayTypeMismatchException();
446447

447448
(int start, int length) = range.GetOffsetAndLength(array.Length);
@@ -454,7 +455,7 @@ public static Span<T> AsSpan<T>(this T[] array, Range range)
454455
/// <param name="text">The target string.</param>
455456
/// <remarks>Returns default when <paramref name="text"/> is null.</remarks>
456457
[MethodImpl(MethodImplOptions.AggressiveInlining)]
457-
public static ReadOnlySpan<char> AsSpan(this string text)
458+
public static ReadOnlySpan<char> AsSpan(this string? text)
458459
{
459460
if (text == null)
460461
return default;
@@ -472,7 +473,7 @@ public static ReadOnlySpan<char> AsSpan(this string text)
472473
/// Thrown when the specified <paramref name="start"/> index is not in range (&lt;0 or &gt;text.Length).
473474
/// </exception>
474475
[MethodImpl(MethodImplOptions.AggressiveInlining)]
475-
public static ReadOnlySpan<char> AsSpan(this string text, int start)
476+
public static ReadOnlySpan<char> AsSpan(this string? text, int start)
476477
{
477478
if (text == null)
478479
{
@@ -498,7 +499,7 @@ public static ReadOnlySpan<char> AsSpan(this string text, int start)
498499
/// Thrown when the specified <paramref name="start"/> index or <paramref name="length"/> is not in range.
499500
/// </exception>
500501
[MethodImpl(MethodImplOptions.AggressiveInlining)]
501-
public static ReadOnlySpan<char> AsSpan(this string text, int start, int length)
502+
public static ReadOnlySpan<char> AsSpan(this string? text, int start, int length)
502503
{
503504
if (text == null)
504505
{
@@ -522,7 +523,7 @@ public static ReadOnlySpan<char> AsSpan(this string text, int start, int length)
522523
/// <summary>Creates a new <see cref="ReadOnlyMemory{T}"/> over the portion of the target string.</summary>
523524
/// <param name="text">The target string.</param>
524525
/// <remarks>Returns default when <paramref name="text"/> is null.</remarks>
525-
public static ReadOnlyMemory<char> AsMemory(this string text)
526+
public static ReadOnlyMemory<char> AsMemory(this string? text)
526527
{
527528
if (text == null)
528529
return default;
@@ -537,7 +538,7 @@ public static ReadOnlyMemory<char> AsMemory(this string text)
537538
/// <exception cref="System.ArgumentOutOfRangeException">
538539
/// Thrown when the specified <paramref name="start"/> index is not in range (&lt;0 or &gt;text.Length).
539540
/// </exception>
540-
public static ReadOnlyMemory<char> AsMemory(this string text, int start)
541+
public static ReadOnlyMemory<char> AsMemory(this string? text, int start)
541542
{
542543
if (text == null)
543544
{
@@ -555,7 +556,7 @@ public static ReadOnlyMemory<char> AsMemory(this string text, int start)
555556
/// <summary>Creates a new <see cref="ReadOnlyMemory{T}"/> over the portion of the target string.</summary>
556557
/// <param name="text">The target string.</param>
557558
/// <param name="startIndex">The index at which to begin this slice.</param>
558-
public static ReadOnlyMemory<char> AsMemory(this string text, Index startIndex)
559+
public static ReadOnlyMemory<char> AsMemory(this string? text, Index startIndex)
559560
{
560561
if (text == null)
561562
{
@@ -580,7 +581,7 @@ public static ReadOnlyMemory<char> AsMemory(this string text, Index startIndex)
580581
/// <exception cref="System.ArgumentOutOfRangeException">
581582
/// Thrown when the specified <paramref name="start"/> index or <paramref name="length"/> is not in range.
582583
/// </exception>
583-
public static ReadOnlyMemory<char> AsMemory(this string text, int start, int length)
584+
public static ReadOnlyMemory<char> AsMemory(this string? text, int start, int length)
584585
{
585586
if (text == null)
586587
{
@@ -604,7 +605,7 @@ public static ReadOnlyMemory<char> AsMemory(this string text, int start, int len
604605
/// <summary>Creates a new <see cref="ReadOnlyMemory{T}"/> over the portion of the target string.</summary>
605606
/// <param name="text">The target string.</param>
606607
/// <param name="range">The range used to indicate the start and length of the sliced string.</param>
607-
public static ReadOnlyMemory<char> AsMemory(this string text, Range range)
608+
public static ReadOnlyMemory<char> AsMemory(this string? text, Range range)
608609
{
609610
if (text == null)
610611
{

src/System.Private.CoreLib/shared/System/MemoryExtensions.Trim.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
#nullable enable
56
using System.Diagnostics;
67

78
namespace System

src/System.Private.CoreLib/shared/System/MemoryExtensions.cs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
#nullable enable
56
using System.Collections.Generic;
67
using System.Runtime.CompilerServices;
78
using System.Runtime.InteropServices;
@@ -981,7 +982,7 @@ public static void Reverse<T>(this Span<T> span)
981982
/// Creates a new span over the target array.
982983
/// </summary>
983984
[MethodImpl(MethodImplOptions.AggressiveInlining)]
984-
public static Span<T> AsSpan<T>(this T[] array)
985+
public static Span<T> AsSpan<T>(this T[]? array)
985986
{
986987
return new Span<T>(array);
987988
}
@@ -999,7 +1000,7 @@ public static Span<T> AsSpan<T>(this T[] array)
9991000
/// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=Length).
10001001
/// </exception>
10011002
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1002-
public static Span<T> AsSpan<T>(this T[] array, int start, int length)
1003+
public static Span<T> AsSpan<T>(this T[]? array, int start, int length)
10031004
{
10041005
return new Span<T>(array, start, length);
10051006
}
@@ -1084,7 +1085,7 @@ public static Span<T> AsSpan<T>(this ArraySegment<T> segment, Range range)
10841085
/// <summary>
10851086
/// Creates a new memory over the target array.
10861087
/// </summary>
1087-
public static Memory<T> AsMemory<T>(this T[] array) => new Memory<T>(array);
1088+
public static Memory<T> AsMemory<T>(this T[]? array) => new Memory<T>(array);
10881089

10891090
/// <summary>
10901091
/// Creates a new memory over the portion of the target array beginning
@@ -1097,13 +1098,13 @@ public static Span<T> AsSpan<T>(this ArraySegment<T> segment, Range range)
10971098
/// <exception cref="System.ArgumentOutOfRangeException">
10981099
/// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=array.Length).
10991100
/// </exception>
1100-
public static Memory<T> AsMemory<T>(this T[] array, int start) => new Memory<T>(array, start);
1101+
public static Memory<T> AsMemory<T>(this T[]? array, int start) => new Memory<T>(array, start);
11011102

11021103
/// <summary>
11031104
/// Creates a new memory over the portion of the target array starting from
11041105
/// 'startIndex' to the end of the array.
11051106
/// </summary>
1106-
public static Memory<T> AsMemory<T>(this T[] array, Index startIndex)
1107+
public static Memory<T> AsMemory<T>(this T[]? array, Index startIndex)
11071108
{
11081109
if (array == null)
11091110
{
@@ -1129,13 +1130,13 @@ public static Memory<T> AsMemory<T>(this T[] array, Index startIndex)
11291130
/// <exception cref="System.ArgumentOutOfRangeException">
11301131
/// Thrown when the specified <paramref name="start"/> or end index is not in the range (&lt;0 or &gt;=Length).
11311132
/// </exception>
1132-
public static Memory<T> AsMemory<T>(this T[] array, int start, int length) => new Memory<T>(array, start, length);
1133+
public static Memory<T> AsMemory<T>(this T[]? array, int start, int length) => new Memory<T>(array, start, length);
11331134

11341135
/// <summary>
11351136
/// Creates a new memory over the portion of the target array beginning at inclusive start index of the range
11361137
/// and ending at the exclusive end index of the range.
11371138
/// </summary>
1138-
public static Memory<T> AsMemory<T>(this T[] array, Range range)
1139+
public static Memory<T> AsMemory<T>(this T[]? array, Range range)
11391140
{
11401141
if (array == null)
11411142
{
@@ -1209,7 +1210,7 @@ public static Memory<T> AsMemory<T>(this ArraySegment<T> segment, int start, int
12091210
/// </exception>
12101211
/// </summary>
12111212
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1212-
public static void CopyTo<T>(this T[] source, Span<T> destination)
1213+
public static void CopyTo<T>(this T[]? source, Span<T> destination)
12131214
{
12141215
new ReadOnlySpan<T>(source).CopyTo(destination);
12151216
}
@@ -1226,7 +1227,7 @@ public static void CopyTo<T>(this T[] source, Span<T> destination)
12261227
/// </exception>
12271228
/// </summary>
12281229
[MethodImpl(MethodImplOptions.AggressiveInlining)]
1229-
public static void CopyTo<T>(this T[] source, Memory<T> destination)
1230+
public static void CopyTo<T>(this T[]? source, Memory<T> destination)
12301231
{
12311232
source.CopyTo(destination.Span);
12321233
}

0 commit comments

Comments
 (0)