Action<Span<byte>> throws compilation error, but delegate void TestMeDelegate(Span<byte> data) doesn't

449 Views Asked by At

Examine the following code.

class Program
{
    delegate void TestMeDelegate(Span<byte> data);

    static void Main(string[] args)
    {
        TestMeDelegate testMeDelegate = TestMe;
        Action<Span<byte>> testMeAction = TestMe;
    }

    static void TestMe(Span<byte> data)
    {
    }
}

The row using testMeDelegate works, but the row using testMeAction throws

The type 'Span<byte>' may not be used as a type argument

I am targeting.net 4.7.2 with the System.Memory nuget version 4.5.1

Langversion is set to C# latest minor version (latest) should be 7.3

Questions:

Is this simply a compiler bug?

What are the differences between Action and delegate in this scenario?

1

There are 1 best solutions below

2
Wazner On BEST ANSWER

It's exactly as the error describes.

The Span<T> type is a ref struct, meaning it's storage location can only be on the stack (So not on the heap). The compiler will output diagnostics for cases were this can't be guaranteed.

The problem is that the compiler can't determine this with generics. Although there are some situations that the compiler could detect (like yours), the compiler team has decided not to allow ref struct types to be used as generic types at all.

I don't know the exact reasoning why they don't properly check this for generic types, but some I can imagine are:

  • Would increase complexity of the compiler by too much
  • It'll be very difficult, if possible at all, to generate proper diagnostic messages for cases where a type can not be used as generic parameter for a given type.