Using Span and Memory to read UTF8 from a socket I am experimenting with Span&lt;&gt; and Memory&lt;&gt; and checking how to use it for example for reading UTF8 text from a NetworkStream using Read(Span&lt;Byte&gt;). I created a fake method that simulates the byte read, and although this code works for the test, I am wondering if this is the right way of doing the most with these new structures in terms of efficiency and memory.

static void Main(string[] args)
{
    Memory&lt;byte&gt; byteMemory = new byte[3];
    Memory&lt;char&gt; charMemory = new char[1024];

    var byteMemoryPos = 0;
    var byteMemoryReaded = 0;
    var charMemoryPos = 0;
    var readed = -1;

    var decoder = Encoding.UTF8.GetDecoder();

    do
    {
        // pass the sliced part of the memory where I want to write as span
        readed = FakeNetworkStreamRead(byteMemory.Slice(byteMemoryPos + byteMemoryReaded).Span);
        Console.WriteLine($"Readed {readed} bytes");

        byteMemoryReaded += readed;

        // pass the sliced part of the memory I want to parse, and the part 
        // of the char buffer where I want to write
        decoder.Convert(byteMemory.Slice(byteMemoryPos, byteMemoryReaded).Span,
                        charMemory.Slice(charMemoryPos).Span,
                        false, out int bytesUsed, out int charsUsed, out bool completed);

        // update offsets and counts
        byteMemoryPos -= bytesUsed;
        charMemoryPos += charsUsed;
        byteMemoryReaded -= bytesUsed;

        // reset offset if nothing to read
        if (byteMemoryReaded == 0)
            byteMemoryPos = 0;
    }
    while (readed != 0);

    Console.WriteLine(new string(charMemory.Slice(0, charMemoryPos).Span));
}

static int _position = 0;
static byte[] _data = Encoding.UTF8.GetBytes("Hi this is test!!");

/// &lt;summary&gt;
/// Pretends to be NetworkStream.Read, that only manages to read 5 bytes each time
/// &lt;/summary&gt;
/// &lt;param name="span"&gt;&lt;/param&gt;
/// &lt;returns&gt;&lt;/returns&gt;
static int FakeNetworkStreamRead(Span&lt;byte&gt; span)
{
    var pending = Math.Min(_data.Length - _position, span.Length);
    pending = Math.Min(pending, 5);
    for (int i = _position, j = 0; i &lt; _position + pending; j++, i++)
    {
        span[j] = _data[i];
    }
    _position += pending;
    return pending;
}
I have no experience with Span&lt;T&gt; or Memory&lt;T&gt; so the following is just some general considerations on coding etc.



In FakeNetworkStreamRead(...): why have a internal limit of 5 bytes? Why not let the length of the Span&lt;T&gt; argument determine the maximum bytes to read?



Why are you using a Memory&lt;T&gt; as buffer, when reading from the stream?:

Memory&lt;byte&gt; byteMemory = new byte[3];


Why not just a Span, because you only use it as a such and not holding or collecting any data in it:

Span&lt;byte&gt; byteSpan = new byte[3];




IMO you should change the do {} while(...) loop to a while (...) loop, because, if the stream is empty you do a "lot" of work in the first round trip for no reason:

  int read = 0;

  while ((read = FakeNetworkStreamRead(byteSpan)) &gt; 0)
  {
    ...
  }




With the above in mind I've tried to refactor your code to: 

static int FakeNetworkStreamRead(Span&lt;byte&gt; span)
{
  int stop = Math.Min(_position + span.Length, _data.Length);
  int i = 0;

  for (; _position &lt; stop; i++, _position++)
  {
    span[i] = _data[_position];
  }

  return i;
}



static void Main(string[] args)
{
  Span&lt;byte&gt; byteSpan = new byte[3];
  Memory&lt;char&gt; charMemory = new char[1024];

  var charMemoryPos = 0;
  var decoder = Encoding.UTF8.GetDecoder();
  int read = 0;

  while ((read = FakeNetworkStreamRead(byteSpan)) &gt; 0)
  {
    Console.WriteLine($"Read {read} bytes");

    // pass the sliced part of the memory I want to parse, and the part 
    // of the char buffer where I want to write
    decoder.Convert(byteSpan.Slice(0, read),
                    charMemory.Slice(charMemoryPos).Span,
                    false, out int bytesUsed, out int charsUsed, out bool completed);

    // update offsets and counts
    charMemoryPos += charsUsed;
  }

  Console.WriteLine(new string(charMemory.Slice(0, charMemoryPos).Span));
}




In order to flush the decoder state, the do {} while(...) loop is useful anyway:

static void Main(string[] args)
{
  int bufferLength = 3;
  Span&lt;byte&gt; byteSpan = new byte[bufferLength];
  Memory&lt;char&gt; charMemory = new char[1024];

  var charMemoryPos = 0;
  var decoder = Encoding.UTF8.GetDecoder();
  int read = 0;

  do 
  {
    read = FakeNetworkStreamRead(byteSpan);

    decoder.Convert(byteSpan.Slice(0, read),
                    charMemory.Slice(charMemoryPos).Span,
                    read == 0, out int bytesUsed, out int charsUsed, out bool completed);

    Console.WriteLine($"Read {read} bytes -&gt; Used: {bytesUsed} -&gt; Completed: {completed} -&gt; CharUsed: {charsUsed} -&gt; {decoder.FallbackBuffer.Remaining}");

    charMemoryPos += charsUsed;
  } while (read &gt; 0) ;

  Console.WriteLine(new string(charMemory.Slice(0, charMemoryPos).Span);
}


Here the read == 0 argument to decoder.Convert(...) becomes true at the end of the stream, which will flush the state and clears the internal buffer of decoder