title: Need a workaround to access ReadOnlySpan<T> inside a function that returns an IEnumerable
body: <p>while dealing with native code interop I decided it was the time to learn and try new Span features of the C# language. Although with many trials, everything was going perfectly fine until I come to the final stage of my very long function for which I insert below just a minimal reproducible sample:</p>
  <pre><code>    [DllImport(dll, SetLastError = true)]
      internal static extern void GetNativeData(out byte lpBuffer, int size, out bytesRead);
  
      ReadOnlySpan&lt;T&gt; ReadArray&lt;T&gt;(ReadOnlySpan&lt;byte&gt; buf, int Length) where T : unmanaged
      {
          var size = Length * Unsafe.SizeOf&lt;T&gt;();
          if (buf.Length &lt; size)
              buf = new byte[size];
              GetNativeData(out MemoryMarshal.GetReference(buf), size, out int read));
              Dh.CreateError(ReadMemoryErr);
          
          return MemoryMarshal.Cast&lt;byte, T&gt;(buf.Slice(0, size));
      }
  
      static IEnumerable&lt;MyClass&gt; GetResult()
      {
          // Here I allocate a buffer
          Span&lt;byte&gt; buf = new byte[1000];
  
          // After a long serie of calls to unmanaged DLL functions I end up with something like this:
          ReadOnlySpan&lt;uint&gt; uintRes = data.ReadArray&lt;uint&gt;(buf, 10);
          ReadOnlySpan&lt;ushort&gt; shortRes = data.ReadArray&lt;ushort&gt;(buf, 10);
          for (int i = 0; i &lt; uintRes.Length; i++)
          {
             // Any access to spans inside this loop result in Error CS4013
             string r = GetFunRes(uintRes[i]);
             IntPtr r2 = GetFunRes2(shortRes[i]);
             yield return new MyClass() { Prop1 = r, Prop2 = r2 };
          }
      }
  </code></pre>
  <p>The error I get is</p>
  <blockquote>
  <p>Error CS4013: Instance of type 'Span' cannot be used inside a
  nested function, query expression, iterator block or async method</p>
  </blockquote>
  <p>Now, I have read that there are <a href="https://endjin.com/blog/2019/10/dotnet-csharp-span-and-async" rel="nofollow noreferrer">workarounds</a> for this. The articles only shows usage for async methods, but it also states that applies to iterators. Unfortunately I have not been able to make this work. I only need to read specific elements of the span and then, yield a result that does not contains any element or reference to the span. It's just that whatever I try to, as soon as I try to access something the compiler fails.</p>
  <p>I have read about <code>Memory&lt;T&gt;</code>, may be that this one could work, but I have some concerns because I have read that the performance is dramatically reduced. People also recommend Span at the first place. I hope I can find a solution because otherwise I will have to restart from scratch my project and rewrite everything because now is tightly tied to Span.</p>
  <p>Thanks in advance for your help</p>
  <blockquote>
  <p>@00110001:</p>
  </blockquote>
  <blockquote>
  <p><code>var uintRes = data.ReadArray&lt;uint&gt;(buf, 10).ToArray();</code></p>
  </blockquote>
  <blockquote>
  <p>I know that this will work, but I suppose that it will make Span usage useless along with the new generics unmanaged features I am trying to take advantage of (<code>ReadArray&lt;T&gt;</code>). If I am not wrong, calling ToArray() it's the same of the old Marshaling style where a new copy is created for each call:</p>
  </blockquote>
  <blockquote>
  <p><code>internal static extern void GetNativeData(out uint[] lpBuffer, int size, out bytesRead);</code></p>
  </blockquote>
  <blockquote>
  <p>@Ian Kemp
  This is how I tried the workaround mentioned in the article:</p>
  </blockquote>
  <pre><code>int len = uintRes.Length;
  for (int i = 0; i &lt; len; i++)
  {
     var res = ParseData(i);
     if (res == ExpectedResult())
        yield return res;
  }
  MyClass ParseData(int index)
  {
       // CS8175: Cannot use ref local 'uintRes, shortRes' inside an anonymous method, lambda expression, or query expression
       string r = GetFunRes(uintRes[index]);
       IntPtr r2 = GetFunRes2(shortRes[index]);
       return new MyClass() { Prop1 = r, Prop2 = r2 };
  }
  </code></pre>