nothrow
nothrow

Reputation: 16168

Struct to it's ReadOnlyMemory<byte> representation

I have following struct:

[StructLayout(LayoutKind.Sequential)]
struct Message
{
     int Header;
     int Data;
}

and I want to send it over the wire, without allocations (using SendAsync(ReadOnlyMemory<byte>)) call.

How can I get the Memory<byte> from given struct?

I ended up in having Span<byte>, and then got stuck.

var message = new Message {
  Header = 1, Data = 3
};
var bytes = MemoryMarshal.AsBytes(
    MemoryMarshal.CreateReadOnlySpan(ref message, 1)
);

Is there any way how to put the struct directly into stream without any allocations?

I'm on netcoreapp2.1.

Upvotes: 5

Views: 3211

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1062745

Something like:

Span<Message> valSpan = stackalloc Message[1];
valSpan[0] = new Message { Header = 123, Data = 456 };
Span<byte> bytes = MemoryMarshal.Cast<Message, byte>(valSpan); // has length 8

Note I'm using Span<T> here. You can do mostly the same stuff with Memory<T> if needed - but you need a backing array or similar, which will usually require an allocation - if not of the array, then of a custom MemoryManager<T>:

var arr = new Message[1];
arr[0] = new Message { Header = 123, Data = 456 };
Memory<byte> bytes = MemoryMarshal.Cast<Message, byte>(arr); // has length 8

Essentially, you are very close here:

MemoryMarshal.CreateReadOnlySpan(ref message, 1)

The trick, though, is to use MemoryMarshal.Cast<TFrom, byte>(...) to get a a span of bytes.

Upvotes: 4

Related Questions