一个包含ValueTuple的结构体是如何满足unmanaged约束条件的,但ValueTuple本身却不能满足呢?

14
考虑以下类型:
  • (int, int) → 托管。
  • struct MyStruct { public (int,int) Value; } → 非托管!
问题:一个非泛型结构体MyStruct,它有一个托管成员(int,int),被评估为托管类型。 期望行为:包含托管成员的结构应该被视为托管,就像struct MyStruct { int? Value; }一样被视为托管。
看起来这两种类型都违反了文档[1][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
    }
}

错误 CS8377:'(int,int)'类型必须是非可空值类型,以及任何嵌套级别的所有字段,才能将其用作泛型类型或方法'Program.DoSomething()'中的参数。 示例2 - 指针或sizeof 对于上述结构,使用指针sizeof运算符的行为相同:
unsafe 
{
    (int, int)* p1;  // → Compile-time error, 
    MyStruct* p2;    // → Compiles
}

错误 CS0208 无法获取、大小或声明托管类型的指针('(int, int)')。
问题:
1. 包含 ValueTuple 的结构体如何被视为“非托管”,并且可以满足“非托管”约束条件,而 ValueTuple 被视为托管?
2. 具有 ValueTupple 和包含 Nullable 的结构体如何被区别对待?

备注1:我认为这个问题与Unmanaged constructed types提案(由DavidG在评论中解决)不同,因为MyStruct不是泛型。另一方面,虽然int?(int,int)都是托管的,但struct MyStruct { int? Value; }struct MyStruct { (int, int) Value; }的求值结果是不同的。


是的,但这个问题涉及到未经管理的构造类型,我猜元组也属于同一类别。 - DavidG
有趣的事实:Resharper将这个第一行(DoSomething<MyStruct>())视为相同的错误。 - DavidG
当然这是一个不同的问题,我只是觉得分享一下很有趣。 - DavidG
我认为这是编译器错误。我建议在Rosyln存储库上开启一个问题。 - John
我的评论中链接到Github问题的内容真的被标记并删除了吗? - DavidG
显示剩余11条评论
1个回答

9
感谢您的报告。这只是编译器中的一个错误。当元组用作字段时,应该将其注册为通用类型,因此在非托管类型中无效。它似乎被评估为tulpe,而忽略了这个检查。
好消息是,在C#8.0中,这个限制将消失。类型(int, int)是一个有效的非托管类型

谢谢!看起来它被评估为“元组”…… → 您是否意味着被评估为“非泛型结构体”?因为如果它被评估为“元组/值元组”,由于它们是托管类型,那么struct MyStruct { (int,int) Value; }应该被评估为“托管”,而实际上它被评估为了“非托管”。 - Reza Aghaei

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接