Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
732 views
in Technique[技术] by (71.8m points)

c# - Self referencing generic member in struct

I need to broaden my understanding of how structs are compiled when using generics.

I have the following code, which works

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

}

This prints 'Size of test is: 4'

However, if I change TestStruct to attempt to provide its own size:

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

I get a runtime error: System.TypeLoadException: Could not load type 'TestStructGenerics.TestStruct' from assembly.

I'm guessing it has to do with the compiler being unable to create the struct compile time. Or perhaps a problem with circular references when handling the generic resolution.

EDIT:

I just realized that I can achieve what I want by changing the second case to:

public struct TestStruct
{
    public GenericStruct<TestStruct> Header => new GenericStruct<TestStruct>();
    public int TestValue;
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

According to Eric Lippert's comments in this Roslyn issue, it is unclear whether this problem is a CLR type loader limitation or whether programs of this sort are invalid, and, if they are invalid, whether the C# compiler should detect it and emit an error. Practically, it appears that, until the authorities decide, we have to avoid type loops between structs regardless of the mode that introduces dependence - instance field (that's never going to work because the struct would be infinite size), static field, implemented generic interface, or generic argument. One can break these struct type loops at compile time by changing some struct in the loop to a class, or at run time by going through object or interface and casting.

See also the corresponding CLR issue.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...