为什么泛型类中的嵌套结构体被认为是“托管”的?

20

我有以下简单的测试:

class C<T>
{
    public struct A
    {
        int x;
    }
}

class Program
{
    static unsafe void Main(string[] args)
    {
        IntPtr p = new IntPtr();

        var a = (C<int>.A*)p.ToPointer();
    }
}

该代码生成错误 CS0208:
Cannot take the address of, get the size of, or declare a pointer to a managed
type ('C<int>.A')

有人能解释一下为什么在这种情况下struct被认为是“托管”的吗?


3
因为相同的原因,通用结构被认为是受管理的。 - user541686
2个回答

20

C# 5规范中的第18.2节:

非托管类型是指任何不是引用类型或构造类型的类型,并且在任何嵌套层次上都不包含引用类型或构造类型字段。

现在你可能会想知道 C<int>.A 是否符合构造类型的定义(它显然不是引用类型)。答案是肯定的。第4.4节定义了构造类型。它明确表示嵌套类型被认为是构造类型。下面使用 Outer<T>.Inner 作为示例:

class Outer<T>
{
    public class Inner {...}
    public Inner i;             // Type of i is Outer<T>.Inner
}

一个可能显而易见(并且与问题无直接关系)的额外要点是,Outer<string>.Inner 是完全不同于 Outer<int>.Inner 的类型,如果您尝试将一个类型的变量设置为另一个类型的值,则会生成“无法隐式转换类型”的错误。 - Grax32
该类是通用的这一事实可以通过MSIL使用的语法更加清晰地表达,即:"Outer`1/Inner<T>"。具体地,类型参数实际上全部位于最嵌套的级别。在MSIL或reflection.emit级别上,可以创建一个嵌套在Outer<T>中的非泛型类,但是C#不允许这样做,并且可能在引用此类时遇到问题。 - Kevin Cathcart

7
因为C的一部分T也属于A,这意味着A也是通用的。所有的通用类型都被视为受控的。
我猜想,可能会检查A是否使用了T并据此决定。但正如所有语言特性一样,这个特性的实现并没有太多的回报价值。

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