Consider the following types:
(int, int) → managed.struct MyStruct { public (int,int) Value; } → unmanaged!Problem: A non-generic structure MyStruct, which has a managed member (int,int) has been evaluated as managed type.
Expected Behavior: A structure which contains a managed member, should be considered as managed, the same way the struct MyStruct { int? Value; } are considered as managed.
It seems both types are behaving against the documentations [1] and [2].
Example 1 - unmanaged Constraint
class Program
{
static void DoSomething<T>() where T : unmanaged { }
struct MyStruct { public (int, int) Value; }
static void Main(string[] args)
{
DoSomething<MyStruct>(); // → OK
DoSomething<(int, int)>(); // → Shows compile-time error
}
}
Error CS8377 The type '(int, int)' must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter 'T' in the generic type or method 'Program.DoSomething()'
Example 2 - pointer or sizeof
Using above structure, the behavior is the same for pointers or sizeof operator:
unsafe
{
(int, int)* p1; // → Compile-time error,
MyStruct* p2; // → Compiles
}
Error CS0208 Cannot take the address of, get the size of, or declare a pointer to a managed type('(int, int)')
Question
How do a struct containing ValueTuple is considered as unmanaged and can satisfy unmanaged constraint while the ValueTuple is considered as managed?
How a struct having ValueTupple<T1, T2> and a struct containing Nullable<T> are treated differently?
Note 1: IMO the issue is different from the Proposal: Unmanaged constructed types (addressed by DavidG in comments), because MyStruct is not generic, on the other hand while int? and (int,int) both are managed, but struct MyStruct { int? Value; } and struct MyStruct { (int, int) Value; } evaluated differently.
Thanks for reporting. This is just a bug in the compiler. The tuple when used as a field should be registering as a generic type and hence invalid in an unmanaged type. It appears to be evaluating as a tulpe instead and missing this check.
Good news is that in C# 8.0 this restriction will be going away. The type (int, int) is a valid unmanaged type.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With