/// Memory represents a contiguous region of arbitrary memory similar to <see cref="Span{T}"/>.
/// Unlike <see cref="Span{T}"/>, it is not a byref-like type.
/// </summary>
- [DebuggerDisplay("{DebuggerDisplay,nq}")]
[DebuggerTypeProxy(typeof(MemoryDebugView<>))]
+ [DebuggerDisplay("{ToString(),raw}")]
public readonly struct Memory<T>
{
// NOTE: With the current implementation, Memory<T> and ReadOnlyMemory<T> must have the same layout,
public static implicit operator ReadOnlyMemory<T>(Memory<T> memory) =>
Unsafe.As<Memory<T>, ReadOnlyMemory<T>>(ref memory);
- //Debugger Display = {T[length]}
- private string DebuggerDisplay => string.Format("{{{0}[{1}]}}", typeof(T).Name, _length);
-
/// <summary>
/// Returns an empty <see cref="Memory{T}"/>
/// </summary>
public bool IsEmpty => _length == 0;
/// <summary>
+ /// For <see cref="Memory{Char}"/>, returns a new instance of string that represents the characters pointed to by the memory.
+ /// Otherwise, returns a <see cref="string"/> with the name of the type and the number of elements.
+ /// </summary>
+ public override string ToString()
+ {
+ if (typeof(T) == typeof(char))
+ {
+ return (_object is string str) ? str.Substring(_index, _length) : Span.ToString();
+ }
+ return string.Format("System.Memory<{0}>[{1}]", typeof(T).Name, _length);
+ }
+
+ /// <summary>
/// Forms a slice out of the given memory, beginning at 'start'.
/// </summary>
/// <param name="start">The index at which to begin this slice.</param>
}
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
- public T[] Items
- {
- // This is a work around since we cannot use _memory.ToArray() due to
- // https://devdiv.visualstudio.com/DevDiv/_workitems?id=286592
- get
- {
- if (MemoryMarshal.TryGetArray(_memory, out ArraySegment<T> segment))
- {
- T[] array = new T[_memory.Length];
- Array.Copy(segment.Array, segment.Offset, array, 0, array.Length);
- return array;
- }
-
- if (typeof(T) == typeof(char) &&
- MemoryMarshal.TryGetString((ReadOnlyMemory<char>)(object)_memory, out string text, out int start, out int length))
- {
- return (T[])(object)text.Substring(start, length).ToCharArray();
- }
-
-#if FEATURE_PORTABLE_SPAN
- return SpanHelpers.PerTypeValues<T>.EmptyArray;
-#else
- return Array.Empty<T>();
-#endif // FEATURE_PORTABLE_SPAN
- }
- }
+ public T[] Items => _memory.ToArray();
}
}
/// Represents a contiguous region of memory, similar to <see cref="ReadOnlySpan{T}"/>.
/// Unlike <see cref="ReadOnlySpan{T}"/>, it is not a byref-like type.
/// </summary>
- [DebuggerDisplay("{DebuggerDisplay,nq}")]
[DebuggerTypeProxy(typeof(MemoryDebugView<>))]
+ [DebuggerDisplay("{ToString(),raw}")]
public readonly struct ReadOnlyMemory<T>
{
// NOTE: With the current implementation, Memory<T> and ReadOnlyMemory<T> must have the same layout,
_length = length;
}
- //Debugger Display = {T[length]}
- private string DebuggerDisplay => string.Format("{{{0}[{1}]}}", typeof(T).Name, _length);
-
/// <summary>
/// Defines an implicit conversion of an array to a <see cref="ReadOnlyMemory{T}"/>
/// </summary>
public bool IsEmpty => _length == 0;
/// <summary>
+ /// For <see cref="ReadOnlyMemory{Char}"/>, returns a new instance of string that represents the characters pointed to by the memory.
+ /// Otherwise, returns a <see cref="string"/> with the name of the type and the number of elements.
+ /// </summary>
+ public override string ToString()
+ {
+ if (typeof(T) == typeof(char))
+ {
+ return (_object is string str) ? str.Substring(_index, _length) : Span.ToString();
+ }
+ return string.Format("System.ReadOnlyMemory<{0}>[{1}]", typeof(T).Name, _length);
+ }
+
+ /// <summary>
/// Forms a slice out of the given memory, beginning at 'start'.
/// </summary>
/// <param name="start">The index at which to begin this slice.</param>