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

Commit 55a68df

Browse files
ahsonkhansafern
authored andcommitted
Adding {RO}Memory<T> debugger view (dotnet/coreclr#14130)
* Adding memory debugger view and fixing ToArray impl. * Addressing PR feedback and adding span debugger display string. * Adding link to specific VSTS instance. * Removing redundant info in comments. Signed-off-by: dotnet-bot-corefx-mirror <dotnet-bot@microsoft.com>
1 parent 16326cf commit 55a68df

File tree

6 files changed

+60
-1
lines changed

6 files changed

+60
-1
lines changed

src/Common/src/CoreLib/System.Private.CoreLib.Shared.projitems

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@
203203
<Compile Include="$(MSBuildThisFileDirectory)System\MarshalByRefObject.cs" />
204204
<Compile Include="$(MSBuildThisFileDirectory)System\MemberAccessException.cs" />
205205
<Compile Include="$(MSBuildThisFileDirectory)System\Memory.cs" />
206+
<Compile Include="$(MSBuildThisFileDirectory)System\MemoryDebugView.cs" />
206207
<Compile Include="$(MSBuildThisFileDirectory)System\MethodAccessException.cs" />
207208
<Compile Include="$(MSBuildThisFileDirectory)System\MidpointRounding.cs" />
208209
<Compile Include="$(MSBuildThisFileDirectory)System\MissingMethodException.cs" />

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
namespace System
1414
{
15+
[DebuggerDisplay("{DebuggerDisplay,nq}")]
16+
[DebuggerTypeProxy(typeof(MemoryDebugView<>))]
1517
public struct Memory<T>
1618
{
1719
// The highest order bit of _index is used to discern whether _arrayOrOwnedMemory is an array or an owned memory
@@ -106,6 +108,9 @@ public static implicit operator ReadOnlyMemory<T>(Memory<T> memory)
106108
return new ReadOnlyMemory<T>((T[])memory._arrayOrOwnedMemory, memory._index, memory._length);
107109
}
108110

111+
//Debugger Display = {T[length]}
112+
private string DebuggerDisplay => string.Format("{{{0}[{1}]}}", typeof(T).Name, _length);
113+
109114
/// <summary>
110115
/// Returns an empty <see cref="Memory{T}"/>
111116
/// </summary>
@@ -281,4 +286,4 @@ private static int CombineHashCodes(int h1, int h2, int h3)
281286
}
282287

283288
}
284-
}
289+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Diagnostics;
6+
7+
namespace System
8+
{
9+
internal sealed class MemoryDebugView<T>
10+
{
11+
private readonly ReadOnlyMemory<T> _memory;
12+
13+
public MemoryDebugView(Memory<T> memory)
14+
{
15+
_memory = memory;
16+
}
17+
18+
public MemoryDebugView(ReadOnlyMemory<T> memory)
19+
{
20+
_memory = memory;
21+
}
22+
23+
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
24+
public T[] Items
25+
{
26+
// This is a work around since we cannot use _memory.ToArray() due to
27+
// https://devdiv.visualstudio.com/DevDiv/_workitems?id=286592
28+
get
29+
{
30+
if (_memory.DangerousTryGetArray(out ArraySegment<T> segment))
31+
{
32+
T[] array = new T[_memory.Length];
33+
Array.Copy(segment.Array, segment.Offset, array, 0, array.Length);
34+
return array;
35+
}
36+
return Array.Empty<T>();
37+
}
38+
}
39+
}
40+
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
namespace System
1414
{
15+
[DebuggerDisplay("{DebuggerDisplay,nq}")]
16+
[DebuggerTypeProxy(typeof(MemoryDebugView<>))]
1517
public struct ReadOnlyMemory<T>
1618
{
1719
// The highest order bit of _index is used to discern whether _arrayOrOwnedMemory is an array or an owned memory
@@ -81,6 +83,9 @@ internal ReadOnlyMemory(OwnedMemory<T> owner, int index, int length)
8183
_length = length;
8284
}
8385

86+
//Debugger Display = {T[length]}
87+
private string DebuggerDisplay => string.Format("{{{0}[{1}]}}", typeof(T).Name, _length);
88+
8489
/// <summary>
8590
/// Defines an implicit conversion of an array to a <see cref="Memory{T}"/>
8691
/// </summary>

src/Common/src/CoreLib/System/ReadOnlySpan.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ namespace System
1515
/// ReadOnlySpan represents a contiguous region of arbitrary memory. Unlike arrays, it can point to either managed
1616
/// or native memory, or to memory allocated on the stack. It is type- and memory-safe.
1717
/// </summary>
18+
[DebuggerDisplay("{DebuggerDisplay,nq}")]
1819
[IsReadOnly]
1920
[IsByRefLike]
2021
[NonVersionable]
@@ -118,6 +119,9 @@ internal ReadOnlySpan(ref T ptr, int length)
118119
_length = length;
119120
}
120121

122+
//Debugger Display = {T[length]}
123+
private string DebuggerDisplay => string.Format("{{{0}[{1}]}}", typeof(T).Name, _length);
124+
121125
/// <summary>
122126
/// 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
123127
/// would have been stored. Such a reference can be used for pinning but must never be dereferenced.

src/Common/src/CoreLib/System/Span.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ namespace System
2121
/// Span represents a contiguous region of arbitrary memory. Unlike arrays, it can point to either managed
2222
/// or native memory, or to memory allocated on the stack. It is type- and memory-safe.
2323
/// </summary>
24+
[DebuggerDisplay("{DebuggerDisplay,nq}")]
2425
[IsReadOnly]
2526
[IsByRefLike]
2627
[NonVersionable]
@@ -130,6 +131,9 @@ internal Span(ref T ptr, int length)
130131
_length = length;
131132
}
132133

134+
//Debugger Display = {T[length]}
135+
private string DebuggerDisplay => string.Format("{{{0}[{1}]}}", typeof(T).Name, _length);
136+
133137
/// <summary>
134138
/// 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
135139
/// would have been stored. Such a reference can be used for pinning but must never be dereferenced.

0 commit comments

Comments
 (0)