Reputation: 2444
I was researching the best way to return 'views
' into a very large array and found ArraySegment
which perfectly suited my needs. However, I then found Memory<T>
which seems to behave the same, with the exception of requiring a span to view the memory.
For the use-case of creating and writing to views into a massive (2GB+) array, does it matter which one is used?
The reasons for the large arrays are they hold bytes of an image.
Upvotes: 22
Views: 5487
Reputation: 7355
Resurrecting this in case someone bumps into this question.
When to use ArraySegment over Memory?
Never, unless you need to call something old that expects an ArraySegment<T>
, which I doubt will be the case as it was never that popular.
ArraySegment<T>
is just an array, an offset, and a length, which are all exposed directly where you can choose to ignore the offset and length and access the entirety of the array if you want to. There’s also no read-only version of ArraySegment<T>
.
Span<T>
and Memory<T>
can be backed by arrays, similar to ArraySegment<T>
, but also by strings and unmanaged memory (in the form of a pointer in Span<T>
’s case, and by using a custom MemoryManager<T>
in Memory<T>
’s case). They provide better encapsulation by not exposing their underlying data source and have read-only versions for immutable access.
Back then, we had to pass the array/offset/count trio to a lot of APIs (APIs that needed a direct reference of an array), but now that Span<T>
and Memory<T>
exist and are widely supported by most, if not all, .NET APIs that need to interact with continuous blocks of memory, you should have no reason to use an ArraySegment<T>
.
See also: Memory- and span-related types - MS Docs
Upvotes: 13
Reputation: 1379
Memory is sort of a wrapper around Span - one that doesn't have to be on the stack. And as the link provided by CoolBots pointed out it's an addition to arrays and array segments not really a replacement for them.
The main reason you would want to consider using Span/Memory is for performance and flexibility. Span gives you access to the memory directly instead of copying it back and forth to the array, and it allows you to treat the memory in a flexible way. Below I'll go from using the array as bytes to using it as an array of uint.
I'll skip right to Span but you could use AsMemory instead so you could pass that around easier. But it'd still boil down to getting the Span from the Memory.
Here's an example:
const int dataSize = 512;
const int segSize = 256;
byte[] rawdata = new byte[dataSize];
var segment = new ArraySegment<byte>(rawdata, segSize, segSize);
var seg1 = segment.AsSpan();
var seg1Uint = MemoryMarshal.Cast<byte, uint>(seg1);
for (int i = 0; i < segSize / sizeof(uint); ++i)
{
ref var data = ref seg1Uint[i];
data = 0x000066;
}
foreach (var b in rawdata)
Console.WriteLine(b);
Upvotes: 0