Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 657fd9d

Browse files
ahsonkhansafern
authored andcommitted
Add object null checks in Memory<T> APIs to support default (#14816)
* Add object null checks in Memory<T> APIs to support default * Changing Empty property to return default value. * Update use of object null checks * Addressing PR feedback. * Removing typeof char check. * Fix typo Signed-off-by: dotnet-bot-corefx-mirror <dotnet-bot@microsoft.com>
1 parent f3e3d7b commit 657fd9d

File tree

2 files changed

+27
-37
lines changed

2 files changed

+27
-37
lines changed

src/Common/src/CoreLib/System/Memory.cs

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ public readonly struct Memory<T>
2020

2121
// The highest order bit of _index is used to discern whether _object is an array/string or an owned memory
2222
// if (_index >> 31) == 1, object _object is an OwnedMemory<T>
23-
// else, object _object is a T[] or a string. It can only be a string if the Memory<T> was created by
23+
// else, object _object is a T[] or a string. It can only be a string if the Memory<T> was created by
2424
// using unsafe / marshaling code to reinterpret a ReadOnlyMemory<char> wrapped around a string as
2525
// a Memory<T>.
2626
private readonly object _object;
@@ -122,7 +122,7 @@ public static implicit operator ReadOnlyMemory<T>(Memory<T> memory) =>
122122
/// <summary>
123123
/// Returns an empty <see cref="Memory{T}"/>
124124
/// </summary>
125-
public static Memory<T> Empty { get; } = Array.Empty<T>();
125+
public static Memory<T> Empty => default;
126126

127127
/// <summary>
128128
/// The number of items in the memory.
@@ -187,15 +187,19 @@ public Span<T> Span
187187
{
188188
// This is dangerous, returning a writable span for a string that should be immutable.
189189
// However, we need to handle the case where a ReadOnlyMemory<char> was created from a string
190-
// and then cast to a Memory<T>. Such a cast can only be done with unsafe or marshaling code,
190+
// and then cast to a Memory<T>. Such a cast can only be done with unsafe or marshaling code,
191191
// in which case that's the dangerous operation performed by the dev, and we're just following
192192
// suit here to make it work as best as possible.
193193
return new Span<T>(ref Unsafe.As<char, T>(ref s.GetRawStringData()), s.Length).Slice(_index, _length);
194194
}
195-
else
195+
else if (_object != null)
196196
{
197197
return new Span<T>((T[])_object, _index, _length);
198198
}
199+
else
200+
{
201+
return default;
202+
}
199203
}
200204
}
201205

@@ -224,7 +228,7 @@ public Span<T> Span
224228

225229
public unsafe MemoryHandle Retain(bool pin = false)
226230
{
227-
MemoryHandle memoryHandle;
231+
MemoryHandle memoryHandle = default;
228232
if (pin)
229233
{
230234
if (_index < 0)
@@ -243,9 +247,8 @@ public unsafe MemoryHandle Retain(bool pin = false)
243247
void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref s.GetRawStringData()), _index);
244248
memoryHandle = new MemoryHandle(null, pointer, handle);
245249
}
246-
else
250+
else if (_object is T[] array)
247251
{
248-
var array = (T[])_object;
249252
var handle = GCHandle.Alloc(array, GCHandleType.Pinned);
250253
void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref array.GetRawSzArrayData()), _index);
251254
memoryHandle = new MemoryHandle(null, pointer, handle);
@@ -258,10 +261,6 @@ public unsafe MemoryHandle Retain(bool pin = false)
258261
((OwnedMemory<T>)_object).Retain();
259262
memoryHandle = new MemoryHandle((OwnedMemory<T>)_object);
260263
}
261-
else
262-
{
263-
memoryHandle = new MemoryHandle(null);
264-
}
265264
}
266265
return memoryHandle;
267266
}
@@ -280,14 +279,10 @@ public bool TryGetArray(out ArraySegment<T> arraySegment)
280279
return true;
281280
}
282281
}
283-
else
282+
else if (_object is T[] arr)
284283
{
285-
T[] arr = _object as T[];
286-
if (typeof(T) != typeof(char) || arr != null)
287-
{
288-
arraySegment = new ArraySegment<T>(arr, _index, _length);
289-
return true;
290-
}
284+
arraySegment = new ArraySegment<T>(arr, _index, _length);
285+
return true;
291286
}
292287

293288
arraySegment = default(ArraySegment<T>);
@@ -333,7 +328,7 @@ public bool Equals(Memory<T> other)
333328
[EditorBrowsable(EditorBrowsableState.Never)]
334329
public override int GetHashCode()
335330
{
336-
return CombineHashCodes(_object.GetHashCode(), _index.GetHashCode(), _length.GetHashCode());
331+
return _object != null ? CombineHashCodes(_object.GetHashCode(), _index.GetHashCode(), _length.GetHashCode()) : 0;
337332
}
338333

339334
private static int CombineHashCodes(int left, int right)

src/Common/src/CoreLib/System/ReadOnlyMemory.cs

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ public ReadOnlyMemory(T[] array, int start, int length)
7575
_length = length;
7676
}
7777

78-
/// <summary>Creates a new memory over the existing object, start, and length. No validation is performed.</summary>
78+
/// <summary>Creates a new memory over the existing object, start, and length. No validation is performed.</summary>
7979
/// <param name="obj">The target object.</param>
8080
/// <param name="start">The index at which to begin the memory.</param>
8181
/// <param name="length">The number of items in the memory.</param>
@@ -104,7 +104,7 @@ internal ReadOnlyMemory(object obj, int start, int length)
104104
/// <summary>
105105
/// Returns an empty <see cref="ReadOnlyMemory{T}"/>
106106
/// </summary>
107-
public static ReadOnlyMemory<T> Empty { get; } = Array.Empty<T>();
107+
public static ReadOnlyMemory<T> Empty => default;
108108

109109
/// <summary>
110110
/// The number of items in the memory.
@@ -169,10 +169,14 @@ public ReadOnlySpan<T> Span
169169
{
170170
return new ReadOnlySpan<T>(ref Unsafe.As<char, T>(ref s.GetRawStringData()), s.Length).Slice(_index, _length);
171171
}
172-
else
172+
else if (_object != null)
173173
{
174174
return new ReadOnlySpan<T>((T[])_object, _index, _length);
175175
}
176+
else
177+
{
178+
return default;
179+
}
176180
}
177181
}
178182

@@ -206,7 +210,7 @@ public ReadOnlySpan<T> Span
206210
/// </param>
207211
public unsafe MemoryHandle Retain(bool pin = false)
208212
{
209-
MemoryHandle memoryHandle;
213+
MemoryHandle memoryHandle = default;
210214
if (pin)
211215
{
212216
if (_index < 0)
@@ -220,9 +224,8 @@ public unsafe MemoryHandle Retain(bool pin = false)
220224
void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref s.GetRawStringData()), _index);
221225
memoryHandle = new MemoryHandle(null, pointer, handle);
222226
}
223-
else
227+
else if (_object is T[] array)
224228
{
225-
var array = (T[])_object;
226229
var handle = GCHandle.Alloc(array, GCHandleType.Pinned);
227230
void* pointer = Unsafe.Add<T>(Unsafe.AsPointer(ref array.GetRawSzArrayData()), _index);
228231
memoryHandle = new MemoryHandle(null, pointer, handle);
@@ -235,10 +238,6 @@ public unsafe MemoryHandle Retain(bool pin = false)
235238
((OwnedMemory<T>)_object).Retain();
236239
memoryHandle = new MemoryHandle((OwnedMemory<T>)_object);
237240
}
238-
else
239-
{
240-
memoryHandle = new MemoryHandle(null);
241-
}
242241
}
243242
return memoryHandle;
244243
}
@@ -258,14 +257,10 @@ public bool DangerousTryGetArray(out ArraySegment<T> arraySegment)
258257
return true;
259258
}
260259
}
261-
else
260+
else if (_object is T[] arr)
262261
{
263-
T[] arr = _object as T[];
264-
if (typeof(T) != typeof(char) || arr != null)
265-
{
266-
arraySegment = new ArraySegment<T>(arr, _index, _length);
267-
return true;
268-
}
262+
arraySegment = new ArraySegment<T>(arr, _index, _length);
263+
return true;
269264
}
270265

271266
arraySegment = default;
@@ -313,7 +308,7 @@ public bool Equals(ReadOnlyMemory<T> other)
313308
[EditorBrowsable(EditorBrowsableState.Never)]
314309
public override int GetHashCode()
315310
{
316-
return CombineHashCodes(_object.GetHashCode(), _index.GetHashCode(), _length.GetHashCode());
311+
return _object != null ? CombineHashCodes(_object.GetHashCode(), _index.GetHashCode(), _length.GetHashCode()) : 0;
317312
}
318313

319314
private static int CombineHashCodes(int left, int right)

0 commit comments

Comments
 (0)