<PackageReference Include="System.Memory" Version="4.6.3" />

MemoryMarshal

public static class MemoryMarshal
Provides a collection of methods for interoperating with Memory<T>, ReadOnlyMemory<T>, Span<T>, and ReadOnlySpan<T>.
using System.Buffers; using System.Collections.Generic; using System.Runtime.CompilerServices; namespace System.Runtime.InteropServices { public static class MemoryMarshal { public static bool TryGetArray<T>(ReadOnlyMemory<T> memory, out ArraySegment<T> segment) { int start; int length; object objectStartLength = memory.GetObjectStartLength(out start, out length); if (start < 0) { if (((MemoryManager<T>)objectStartLength).TryGetArray(out ArraySegment<T> segment2)) { segment = new ArraySegment<T>(segment2.Array, segment2.Offset + (start & 2147483647), length); return true; } } else { T[] array = objectStartLength as T[]; if (array != null) { segment = new ArraySegment<T>(array, start, length & 2147483647); return true; } } if ((length & 2147483647) == 0) { segment = new ArraySegment<T>(System.SpanHelpers.PerTypeValues<T>.EmptyArray); return true; } segment = default(ArraySegment<T>); return false; } public static bool TryGetMemoryManager<T, TManager>(ReadOnlyMemory<T> memory, out TManager manager) where TManager : MemoryManager<T> { int start; int length; TManager val = manager = (memory.GetObjectStartLength(out start, out length) as TManager); return manager != null; } public static bool TryGetMemoryManager<T, TManager>(ReadOnlyMemory<T> memory, out TManager manager, out int start, out int length) where TManager : MemoryManager<T> { TManager val = manager = (memory.GetObjectStartLength(out start, out length) as TManager); start &= 2147483647; if (manager == null) { start = 0; length = 0; return false; } return true; } public static IEnumerable<T> ToEnumerable<T>(ReadOnlyMemory<T> memory) { for (int i = 0; i < memory.Length; i++) { yield return memory.Span[i]; } } public static bool TryGetString(ReadOnlyMemory<char> memory, out string text, out int start, out int length) { int start2; int length2; string text2 = memory.GetObjectStartLength(out start2, out length2) as string; if (text2 != null) { text = text2; start = start2; length = length2; return true; } text = null; start = 0; length = 0; return false; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static T Read<T>(ReadOnlySpan<byte> source) where T : struct { if (System.SpanHelpers.IsReferenceOrContainsReferences<T>()) System.ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T)); if (Unsafe.SizeOf<T>() > source.Length) System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.length); return Unsafe.ReadUnaligned<T>(ref GetReference(source)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool TryRead<T>(ReadOnlySpan<byte> source, out T value) where T : struct { if (System.SpanHelpers.IsReferenceOrContainsReferences<T>()) System.ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T)); if (Unsafe.SizeOf<T>() > (uint)source.Length) { value = default(T); return false; } value = Unsafe.ReadUnaligned<T>(ref GetReference(source)); return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void Write<T>(Span<byte> destination, ref T value) where T : struct { if (System.SpanHelpers.IsReferenceOrContainsReferences<T>()) System.ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T)); if ((uint)Unsafe.SizeOf<T>() > (uint)destination.Length) System.ThrowHelper.ThrowArgumentOutOfRangeException(System.ExceptionArgument.length); Unsafe.WriteUnaligned(ref GetReference(destination), value); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static bool TryWrite<T>(Span<byte> destination, ref T value) where T : struct { if (System.SpanHelpers.IsReferenceOrContainsReferences<T>()) System.ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T)); if (Unsafe.SizeOf<T>() > (uint)destination.Length) return false; Unsafe.WriteUnaligned(ref GetReference(destination), value); return true; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Memory<T> CreateFromPinnedArray<T>(T[] array, int start, int length) { if (array == null) { if (start != 0 || length != 0) System.ThrowHelper.ThrowArgumentOutOfRangeException(); return default(Memory<T>); } if (default(T) == null && array.GetType() != typeof(T[])) System.ThrowHelper.ThrowArrayTypeMismatchException(); if ((uint)start > (uint)array.Length || (uint)length > (uint)(array.Length - start)) System.ThrowHelper.ThrowArgumentOutOfRangeException(); return new Memory<T>((object)array, start, length | -2147483648); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static Span<byte> AsBytes<T>(Span<T> span) where T : struct { if (System.SpanHelpers.IsReferenceOrContainsReferences<T>()) System.ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T)); int length = checked(span.Length * Unsafe.SizeOf<T>()); return new Span<byte>(Unsafe.As<Pinnable<byte>>(span.Pinnable), span.ByteOffset, length); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ReadOnlySpan<byte> AsBytes<T>(ReadOnlySpan<T> span) where T : struct { if (System.SpanHelpers.IsReferenceOrContainsReferences<T>()) System.ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(T)); int length = checked(span.Length * Unsafe.SizeOf<T>()); return new ReadOnlySpan<byte>(Unsafe.As<Pinnable<byte>>(span.Pinnable), span.ByteOffset, length); } public static Memory<T> AsMemory<T>(ReadOnlyMemory<T> memory) { return Unsafe.As<ReadOnlyMemory<T>, Memory<T>>(ref memory); } public unsafe static ref T GetReference<T>(Span<T> span) { if (span.Pinnable == null) return ref Unsafe.AsRef<T>(span.ByteOffset.ToPointer()); return ref Unsafe.AddByteOffset(ref span.Pinnable.Data, span.ByteOffset); } public unsafe static ref T GetReference<T>(ReadOnlySpan<T> span) { if (span.Pinnable == null) return ref Unsafe.AsRef<T>(span.ByteOffset.ToPointer()); return ref Unsafe.AddByteOffset(ref span.Pinnable.Data, span.ByteOffset); } public static Span<TTo> Cast<TFrom, TTo>(Span<TFrom> span) where TFrom : struct where TTo : struct { if (System.SpanHelpers.IsReferenceOrContainsReferences<TFrom>()) System.ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(TFrom)); if (System.SpanHelpers.IsReferenceOrContainsReferences<TTo>()) System.ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(TTo)); checked { int length = (int)unchecked(checked(unchecked((long)span.Length) * unchecked((long)Unsafe.SizeOf<TFrom>())) / Unsafe.SizeOf<TTo>()); return new Span<TTo>(Unsafe.As<Pinnable<TTo>>(span.Pinnable), span.ByteOffset, length); } } public static ReadOnlySpan<TTo> Cast<TFrom, TTo>(ReadOnlySpan<TFrom> span) where TFrom : struct where TTo : struct { if (System.SpanHelpers.IsReferenceOrContainsReferences<TFrom>()) System.ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(TFrom)); if (System.SpanHelpers.IsReferenceOrContainsReferences<TTo>()) System.ThrowHelper.ThrowArgumentException_InvalidTypeWithPointersNotSupported(typeof(TTo)); checked { int length = (int)unchecked(checked(unchecked((long)span.Length) * unchecked((long)Unsafe.SizeOf<TFrom>())) / Unsafe.SizeOf<TTo>()); return new ReadOnlySpan<TTo>(Unsafe.As<Pinnable<TTo>>(span.Pinnable), span.ByteOffset, length); } } } }