2

The following code compiles in both VS2013 and VS2015, for various .NET Framework versions from 2.0 to 4.6.1, but when executed throws a System.TypeLoadException:

namespace Test
{
    struct Foo<T>
    {
    }

    struct Bar<U>
    {
        Foo<Bar<U>> foo;
    }

    class Program
    {
        static void Main(string[] args)
        {
            var x = new Bar<int>();
        }
    }
}

But if either Foo or Bar are changed from a struct to a class, it runs. I'm trying to understand why this doesn't work for two structs. Why is this code failing?

The exception message is:

"System.TypeLoadException occurred Message: A first chance exception of type 'System.TypeLoadException' occurred in mscorlib.dll Additional information: Could not load type 'Test.Bar`1' from assembly 'scratch, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'."

T.S.
  • 18,195
  • 11
  • 58
  • 78
  • 1
    Possible duplicate of [Generics used in struct vs class](http://stackoverflow.com/questions/13731798/generics-used-in-struct-vs-class) – MethodMan Aug 18 '16 at 18:03
  • 1
    What is the message of the TypeLoadException? – Noémie Lord Aug 18 '16 at 18:05
  • The exception message is: "System.TypeLoadException occurred Message: A first chance exception of type 'System.TypeLoadException' occurred in mscorlib.dll Additional information: Could not load type 'Test.Bar`1' from assembly 'scratch, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'." – David Savage Aug 18 '16 at 18:06
  • 1
    Probably related to [CS0523](https://msdn.microsoft.com/en-us/library/7b625z82.aspx)? I get CS0523 when I change `Foo> foo;` to `Bar foo;` – Quantic Aug 18 '16 at 18:18
  • Nice explanation of CS0523 is http://stackoverflow.com/questions/9296251/cycle-in-the-struct-layout-that-doesnt-exist (which is more or less duplicate of this, but not exact) – Alexei Levenkov Aug 18 '16 at 19:32
  • Regarding CS0523, that's not what is happening in the code above. Foo doesn't have any fields specified, so there can't be a cycle in the field layout. Clearly this has to do with the cyclic type parameters, but it works fine if either Foo or Bar is a class instead of a struct. It seems to have something to do with how the CLR handles generics for structs (but not for classes). – David Savage Aug 18 '16 at 20:06

1 Answers1

1

you can't create structs with looped types

similar problems:

struct Foo
{
  Bar bar;
}

struct Bar
{
  Foo foo;
}

or

struct Foo
{
  Foo foo1;
  Foo foo2;
}

classes use references and works fine

generic logic have same problems, but produce the type-errors only at runtime (IL-compile)

your struct Foo<T> suggests to use the T-Type inside the Foo-struct, but this produce a loop in the struct layout

if you really use the T-Type, it produce also an compiler-error:

struct Foo<T>
{
  T demo; // CS0523
}

struct Bar<U>
{
  Foo<Bar<U>> foo; // CS0523
}
MaxKlaxx
  • 713
  • 7
  • 9