{ReadOnly}Memory<T> Extensions
Background
Came up in dotnet/corefx#24389 (comment)
Currently you can use all the Span<T> extensions and methods from Memory<T> by extracting the Span<T> e.g.
memory0.Span.SequenceEqual(memory1.Span);
However this has two downsides
- Not discoverable; you need to use the Span property to find them
- Span can't be used in an
async method; so to use them you need to create a second method and call that
Proposal
Include the second method as extensions on {ReadOnly}Memory<T> that passes through to the Span
public static class MemoryExtensions
{
// Span methods converted to Memory extension
public static void CopyTo<T>(this Memory<T> memory, Memory<T> destination)
=> memory.Span.CopyTo(destination.Span);
public static void CopyTo<T>(this ReadOnlyMemory<T> memory, Memory<T> destination)
=> memory.Span.CopyTo(destination.Span);
public static bool TryCopyTo<T>(this Memory<T> memory, Memory<T> destination)
=> memory.Span.TryCopyTo(destination.Span);
public static bool TryCopyTo<T>(this ReadOnlyMemory<T> memory, Memory<T> destination)
=> memory.Span.TryCopyTo(destination.Span);
public static void Fill<T>(this Memory<T> memory, T value)
=> memory.Span.Fill(value);
// Array extension as per Span extension
public static void CopyTo<T>(this T[] array, Memory<T> destination)
=> array.CopyTo(destination.Span);
// Valid? via Owned memory?
public static ReadOnlyMemory<char> AsReadOnlyMemory(this string text);
// Discoverable conversions as per Span
public static Memory<T> AsMemory<T>(this ArraySegment<T> arraySegment) => arraySegment;
public static Memory<T> AsMemory<T>(this T[] array) => array;
// Span extension pass-throughs
public static int IndexOf(this Memory<byte> memory, byte value)
=> memory.Span.IndexOf(value);
public static int IndexOf(this Memory<byte> memory, ReadOnlyMemory<byte> value)
=> memory.Span.IndexOf(value.Span);
public static int IndexOf(this ReadOnlyMemory<byte> memory, byte value)
=> memory.Span.IndexOf(value);
public static int IndexOf(this ReadOnlyMemory<byte> memory, ReadOnlyMemory<byte> value)
=> memory.Span.IndexOf(value.Span);
public static int IndexOf<T>(this Memory<T> memory, T value)
where T : struct, IEquatable<T>
=> memory.Span.IndexOf(value);
public static int IndexOf<T>(this Memory<T> memory, ReadOnlyMemory<T> value)
where T : struct, IEquatable<T>
=> memory.Span.IndexOf(value.Span);
public static int IndexOf<T>(this ReadOnlyMemory<T> memory, T value)
where T : struct, IEquatable<T>
=> memory.Span.IndexOf(value);
public static int IndexOf<T>(this ReadOnlyMemory<T> memory, ReadOnlyMemory<T> value)
where T : struct, IEquatable<T>
=> memory.Span.IndexOf(value.Span);
public static int IndexOfAny(this Memory<byte> memory, byte value0, byte value1)
=> memory.Span.IndexOfAny(value0, value1);
public static int IndexOfAny(this Memory<byte> memory, byte value0, byte value1, byte value2)
=> memory.Span.IndexOfAny(value0, value1, value2);
public static int IndexOfAny(this Memory<byte> memory, ReadOnlyMemory<byte> values)
=> memory.Span.IndexOfAny(values.Span);
public static int IndexOfAny(this ReadOnlyMemory<byte> memory, byte value0, byte value1)
=> memory.Span.IndexOfAny(value0, value1);
public static int IndexOfAny(this ReadOnlyMemory<byte> memory, byte value0, byte value1, byte value2)
=> memory.Span.IndexOfAny(value0, value1, value2);
public static int IndexOfAny(this ReadOnlyMemory<byte> memory, ReadOnlyMemory<byte> values)
=> memory.Span.IndexOfAny(values.Span);
public static bool SequenceEqual(this Memory<byte> first, ReadOnlyMemory<byte> second)
=> first.Span.SequenceEqual(second.Span);
public static bool SequenceEqual(this ReadOnlyMemory<byte> first, ReadOnlyMemory<byte> second)
=> first.Span.SequenceEqual(second.Span);
public static bool SequenceEqual<T>(this Memory<T> first, ReadOnlyMemory<T> value)
where T : struct, IEquatable<T>
=> first.Span.SequenceEqual(value.Span);
public static bool SequenceEqual<T>(this ReadOnlyMemory<T> first, ReadOnlyMemory<T> value)
where T : struct, IEquatable<T>
=> first.Span.SequenceEqual(value.Span);
public static bool StartsWith(this Memory<byte> memory, ReadOnlyMemory<byte> value)
=> memory.Span.StartsWith(value.Span);
public static bool StartsWith(this ReadOnlyMemory<byte> memory, ReadOnlyMemory<byte> value)
=> memory.Span.StartsWith(value.Span);
public static bool StartsWith<T>(this Memory<T> memory, ReadOnlyMemory<T> value)
where T : struct, IEquatable<T>
=> memory.Span.StartsWith(value.Span);
public static bool StartsWith<T>(this ReadOnlyMemory<T> memory, ReadOnlyMemory<T> value)
where T : struct, IEquatable<T>
=> memory.Span.StartsWith(value.Span);
}
Notes
Items that change length can't be replicated due to the backing store e,g, AsBytes, NonPortableCast
Question
Is a string conversion possible?
public static ReadOnlyMemory<char> AsReadOnlyMemory(this string text);
/cc @davidfowl @KrzysztofCwalina @stephentoub @jkotas
{ReadOnly}Memory<T>ExtensionsBackground
Came up in dotnet/corefx#24389 (comment)
Currently you can use all the
Span<T>extensions and methods fromMemory<T>by extracting theSpan<T>e.g.However this has two downsides
asyncmethod; so to use them you need to create a second method and call thatProposal
Include the second method as extensions on
{ReadOnly}Memory<T>that passes through to the SpanNotes
Items that change length can't be replicated due to the backing store e,g,
AsBytes,NonPortableCastQuestion
Is a string conversion possible?
/cc @davidfowl @KrzysztofCwalina @stephentoub @jkotas