结构中的自引用泛型成员

本文关键字:泛型 成员 自引用 结构 | 更新日期: 2023-09-27 18:12:37

我需要扩大我对使用泛型时如何编译结构体的理解。

我有下面的代码,它工作

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}");
}

打印'Size of test is: 4'

但是,如果我改变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;
}

结构中的自引用泛型成员

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

参见相应的CLR问题