Cycle in the struct layout that doesn't exist

alan2here picture alan2here · Feb 15, 2012 · Viewed 8.6k times · Source

This is a simplified version of some of my code:

public struct info
{
    public float a, b;
    public info? c;

    public info(float a, float b, info? c = null)
    {
        this.a = a;
        this.b = b;
        this.c = c;
    }
}

The problem is the error Struct member 'info' causes a cycle in the struct layout. I'm after struct like value type behaviour. I could simulate this using a class and a clone member function, but I don't see why I should need to.

How is this error true? Recursion could perhaps cause construction forever in some similar situations, but I can't think of any way that it could in this case. Below are examples that ought to be fine if the program would compile.

new info(1, 2);
new info(1, 2, null);
new info(1, 2, new info(3, 4));

edit:

The solution I used was to make "info" a class instead of a struct and giving it a member function to returned a copy that I used when passing it. In effect simulating the same behaviour as a struct but with a class.

I also created the following question while looking for an answer.

Value type class definition in C#?

Answer

Mark Byers picture Mark Byers · Feb 15, 2012

It's not legal to have a struct that contains itself as a member. This is because a struct has fixed size, and it must be at least as large as the sum of the sizes of each of its members. Your type would have to have 8 bytes for the two floats, at least one byte to show whether or not info is null, plus the size of another info. This gives the following inequality:

 size of info >= 4 + 4 + 1 + size of info

This is obviously impossible as it would require your type to be infinitely large.

You have to use a reference type (i.e. class). You can make your class immutable and override Equals and GetHashCode to give value-like behaviour, similar to the String class.