C# Error
CS4013 – Instance of type ‘{0}’ cannot be used inside a nested function, query expression, iterator block or async method
Reason for the Error & Solution
Instance of type cannot be used inside a nested function, query expression, iterator block or async method
Example
The following sample generates CS4013:
public class C
{
public static IEnumerable<string> Lines(char[] text)
{
ReadOnlySpan<char> chars = text;
var index = chars.IndexOf('\n');
while (index > 0)
{
yield return chars[..index].ToString();
chars = chars[(index + 1)..];
index = chars.IndexOf('\n');
}
yield return chars.ToString();
}
}
This enumerator method extracts lines of text from a character array. It naively tries to use ReadOnlySpan<T>
to improve performance.
To correct this error
Lines(char[] text)
is an enumerator function. An enumerator function compiles the method’s body into a state machine that manages the sequence of states the iterator function goes through while processing. That state machine is implemented as a generated class, and the state is implemented as variables within that class. That captured local state is forced from a stack context to a heap context. Since ref struct
s like ReadOnlySpan<T>
cannot be stored in the heap, the CS4013 error is raised. To continue to use a ReadOnlySpan<T>
, to correct this error, the method must be re-implemented as a non-iterator function, for example:
public static IEnumerable<string> Lines2(char[] text)
{
ReadOnlySpan<char> chars = text;
var lines = new List<string>();
var index = chars.IndexOf('\n');
while (index > 0)
{
lines.Add(chars[..index].ToString());
chars = chars[(index+1)..];
index = chars.IndexOf('\n');
}
lines.Add(chars.ToString());
return lines;
}
To continue to use an iterator function, to correct this error, the method must be re-implemented to avoid using ReadOnlySpan<T>
, for example:
public static IEnumerable<string> Lines2(char[] chars)
{
var startIndex = 0;
var index = Array.IndexOf(chars,'\n');
while (index > 0)
{
yield return new string(chars, startIndex, index);
startIndex = index+1;
index = Array.IndexOf(chars, '\n', startIndex);
}
yield return new string(chars, startIndex, chars.Length - startIndex);
}