在结构中自引用泛型成员

时间:2016-10-12 09:34:19

标签: c# .net generics

我需要扩展我对使用泛型时编译结构的理解。

我有以下代码,可以使用

public struct TestStruct
{
    public GenericStruct<SecondTestStruct> Header;
    public int TestValue;
}

public struct GenericStruct<T>
{
    public int MessageSize => System.Runtime.InteropServices.Marshal.SizeOf(typeof(T));
}

public struct SecondTestStruct
{
    public int TestValue;
}

static void Main(string[] args)
{
    TestStruct test = new TestStruct();
    Console.WriteLine($"Size of test is: {test.Header.MessageSize}");

}

此打印&#39;测试大小为:4&#39;

但是,如果我更改TestStruct以尝试提供自己的大小:

public struct TestStruct
{
    public GenericStruct<TestStruct> Header;
    public int TestValue;
}

我收到运行时错误:System.TypeLoadException: Could not load type 'TestStructGenerics.TestStruct' from assembly.

我猜测它与编译器无法创建结构编译时间有关。或者在处理通用分辨率时可能存在循环引用的问题。

修改

我刚刚意识到我可以通过将第二种情况更改为:

来实现我想要的目标
public struct TestStruct
{
    public GenericStruct<TestStruct> Header => new GenericStruct<TestStruct>();
    public int TestValue;
}

1 个答案:

答案 0 :(得分:1)

根据Eric Lippert在this Roslyn issue中的评论,目前还不清楚这个问题是否是CLR类型加载器限制,或者这类程序是否无效,如果它们无效,C#编译器是否应检测到它并发出错误。实际上,似乎在当局决定之前,我们必须避免结构之间的类型循环而不管引入依赖的模式 - 实例字段(因为结构将是无限大小而永远不会起作用),静态字段,实现的通用接口或通用参数。通过将循环中的某些结构更改为类,或者在运行时通过object或接口和转换,可以在编译时中断这些结构类型循环。

另请参阅corresponding CLR issue