Skip to content

Commit be91a36

Browse files
authored
Avoid Unsafe.As for Memory<T> and ReadOnlyMemory<T> conversion (#111023)
* Use `Unsafe.BitCast`to cast `Memory<T>` and `ReadOnlyMemory<T>` * remove use of `Unsafe`
1 parent 1b71136 commit be91a36

File tree

3 files changed

+5
-11
lines changed

3 files changed

+5
-11
lines changed

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

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,6 @@ namespace System
2020
[DebuggerDisplay("{ToString(),raw}")]
2121
public readonly struct Memory<T> : IEquatable<Memory<T>>
2222
{
23-
// NOTE: With the current implementation, Memory<T> and ReadOnlyMemory<T> must have the same layout,
24-
// as code uses Unsafe.As to cast between them.
25-
2623
// The highest order bit of _index is used to discern whether _object is a pre-pinned array.
2724
// (_index < 0) => _object is a pre-pinned array, so Pin() will not allocate a new GCHandle
2825
// (else) => Pin() needs to allocate a new GCHandle to pin the object.
@@ -187,7 +184,7 @@ internal Memory(object? obj, int start, int length)
187184
/// Defines an implicit conversion of a <see cref="Memory{T}"/> to a <see cref="ReadOnlyMemory{T}"/>
188185
/// </summary>
189186
public static implicit operator ReadOnlyMemory<T>(Memory<T> memory) =>
190-
Unsafe.As<Memory<T>, ReadOnlyMemory<T>>(ref memory);
187+
new ReadOnlyMemory<T>(memory._object, memory._index, memory._length);
191188

192189
/// <summary>
193190
/// Returns an empty <see cref="Memory{T}"/>

src/libraries/System.Private.CoreLib/src/System/ReadOnlyMemory.cs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,12 @@ namespace System
2020
[DebuggerDisplay("{ToString(),raw}")]
2121
public readonly struct ReadOnlyMemory<T> : IEquatable<ReadOnlyMemory<T>>
2222
{
23-
// NOTE: With the current implementation, Memory<T> and ReadOnlyMemory<T> must have the same layout,
24-
// as code uses Unsafe.As to cast between them.
25-
2623
// The highest order bit of _index is used to discern whether _object is a pre-pinned array.
2724
// (_index < 0) => _object is a pre-pinned array, so Pin() will not allocate a new GCHandle
2825
// (else) => Pin() needs to allocate a new GCHandle to pin the object.
29-
private readonly object? _object;
30-
private readonly int _index;
31-
private readonly int _length;
26+
internal readonly object? _object;
27+
internal readonly int _index;
28+
internal readonly int _length;
3229

3330
internal const int RemoveFlagsBitMask = 0x7FFFFFFF;
3431

src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/MemoryMarshal.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ ref Unsafe.As<T, byte>(ref GetReference(span)),
7171
/// as <see cref="Memory{T}"/> but only used for reading to store a <see cref="ReadOnlyMemory{T}"/>.
7272
/// </remarks>
7373
public static Memory<T> AsMemory<T>(ReadOnlyMemory<T> memory) =>
74-
Unsafe.As<ReadOnlyMemory<T>, Memory<T>>(ref memory);
74+
new Memory<T>(memory._object, memory._index, memory._length);
7575

7676
/// <summary>
7777
/// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to the location where the 0th element

0 commit comments

Comments
 (0)