2

For example, say I wanted to make a genetics simulator and I had this very simple struct

public struct person{
    string name;
    int age;
    string hairColor; 

    person father;
    person mother;
}

so that later I could reference the person Joey's parent's hair color with Joey.father.haircolor? I keep getting error:

Struct Member 'person.father' of type 'person' causes a cycle in the struct layout

Is my only option to use a class? For the sake of speed I'd prefer to use a struct since it's all data, but if there's no alternative I can obviously just use a class.

7
  • 7
    I think you've misunderstood how structs work - particularly given your "since it's all data". What do you mean by that? What do you think the difference between a struct and a class is? Commented Jun 7, 2016 at 19:47
  • What @JonSkeet is alluding to is that once you understand the difference between a class and a struct, the problem at hand will be very apparent: msdn.microsoft.com/en-us/library/… Commented Jun 7, 2016 at 19:49
  • I was under the impression from what I've read that structs and classes are close to the same thing, but structs should be used when it's more of a collection of data Commented Jun 7, 2016 at 19:52
  • 1
    You're not entirely wrong. However, as stated below, that structs are of a 'set memory size', and a self-reference would allow it to grow infinitely. (see stackoverflow.com/questions/9296251/…) Commented Jun 7, 2016 at 19:53
  • 1
    Also, aren't you starting to miss C++ pointers? ;) Commented Jun 7, 2016 at 19:55

2 Answers 2

7

Your type Person should be a class for multiple reasons :

  • a struct can not self reference
  • a struct should be considered if the instance will be small and commonly short-lived or are commonly embedded in other objects. It does not seem to be the case.
  • a struct should be considered if all these conditions are met : 1. it logically represents a single value like primitive types 2. it has an instance size under 16 bytes 3.iIt is immutable 4. It will not have to be boxed frequently. It is not the case.
  • if you use a struct, two persons could not share the same father as the variable are passed by value. This will produce a bad design
  • you are interested by speed but usage of a class is faster than a struct, as variable are passed by reference instead of by value
Sign up to request clarification or add additional context in comments.

2 Comments

That's a nice answer indeed.
Your last point needs to be reworded. A variable is passed by value, and a struct is also passed by value. A class is passed by reference. There's little performance difference access either one, since using a register to access the heap vs the stack is very much similar (just different registers). Setting very large struct values many times though can be a bit slower than setting references. In fact, a struct too large will most likely end up in the heap, and not the stack.
0

This is only possible through unsafe (unmanaged) code in C#.

In C (not C#) structs certainly may reference to the same type:

#include <stdio.h>

struct my_struct {
    int id;
    struct my_struct *parent;
};

int main() {
    struct my_struct parent_struct = {
            .id = 0
    };

    struct my_struct *parent_pointer = &parent_struct;

    struct my_struct child_struct = {
            .id = 1, .parent = parent_pointer
    };

    printf("Child's parent id is %d", child_struct.parent->id);
}

But in C#, it is not possible with managed code:

public struct MyStruct
{
    public MyStruct(string name)
    {
        Name = name;
    }

    public string Name { get; set; }

    // does not compile
    public MyStruct Parent { get; set; }
}

Yet it is possible in C# with unmanaged code:

internal class Program
{
    private static void Main(string[] args)
    {
        unsafe
        {
            var parent = new MyStruct("parent");
            var child = new MyStruct("child");
            child.Parent = &parent;

            var parentName = child.Parent->Name;
            Console.WriteLine(parentName);
        }
    }
}

public struct MyStruct
{
    public MyStruct(string name)
    {
        Name = name;
    }

    public string Name { get; set; }

    public unsafe MyStruct* Parent { get; set; }
}

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.