为什么包含 ValueTuple 的结构可以满足非托管约束,而 ValueTuple 本身却不能?

How is it that a struct containing ValueTuple can satisfy unmanaged constraints, but ValueTuple itself cannot?

考虑以下类型:

问题: 具有托管成员 (int,int) 的非泛型结构 MyStruct 已被评估为托管类型。

预期行为: 包含托管成员的结构应被视为托管,与 struct MyStruct { int? Value; } 被视为托管的方式相同。

这两种类型的行为似乎都违反了文档 [1] and [2]

示例 1 - 非托管约束

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()'

示例 2 - 指针或 sizeof

使用上述结构,pointers or sizeof 运算符的行为相同:

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)')

问题

  1. 包含 ValueTuple 的结构如何被视为 unmanaged 并且可以满足 unmanaged 约束,而 ValueTuple 被视为托管?

  2. 如何区别对待具有 ValueTupple<T1, T2> 的结构和包含 Nullable<T> 的结构?


注 1: IMO 问题不同于 Proposal: Unmanaged constructed types(由 DavidG 在评论中解决),因为 MyStruct 是不是通用的,另一方面,虽然 int?(int,int) 都是管理的,但 struct MyStruct { int? Value; }struct MyStruct { (int, int) Value; } 的评估不同。

感谢您的报告。这只是编译器中的一个错误。用作字段的元组应注册为通用类型,因此在 unmanaged type 中无效。它似乎正在评估为一个 tulpe 而错过了这个检查。

好消息是,在 C# 8.0 中,此限制将消失。类型 (int, int) 是有效的 unmanaged type