What's wrong with this C # framework?

Note. My question has several parts. I would appreciate it if you could answer each of the questions instead of just telling me what to do to get this to compile. :)

I am not very familiar with C #. In fact, the reason I don't know much about this is because my class is focused on building efficient algorithms, not teaching us about .NET. However, all of our programs must be written in .NET, and this has not been a problem until now. I have the following code, but it won't compile and I really don't understand why. I have a feeling this should be completely rewritten, but before I do I want to know WHY this is not allowed.

The point of structure is to create a linked list like structure, so I can add another node to the end of the "list" and then traverse and call the nodes in reverse order

private struct BackPointer
{
    public BackPointer previous;
    public string a;
    public string b;
    public BackPointer(BackPointer p, string aa, string bb)
    {
        previous = p;
        a = aa;
        b = bb;
    }
}

      

then later in my code there is something like

BackPointer pointer = new BackPointer();
pointer = new BackPointer(pointer, somestring_a, somestring_b);

      

The compilation error I am getting is Struct member 'MyClass.BackPointer.previous' of type 'MyClass.BackPointer' causes a cycle in the struct layout

This seems like an obvious mistake. I don't like the fact that I am passing a struct in the constructor of the same struct. But why is it not allowed? I would guess that this code would just create a new node in the list and return that node a pointer back to the previous node, but apparently this is not what will happen. So what happens then? Finally, what is the recommended way to solve this problem? I thought to just say it is unmanageable, just handle my pointers by hand, but I only know how to do it in C ++. I don't know what could go wrong in C #

+3


source to share


5 answers


But why is it not allowed?

This is a structure - a value type. This means that wherever you have a variable of this type, this variable contains all the fields within the structure, directly inline. If something contains (or creates a more complex loop), then you obviously cannot allocate enough space for that - because it must have enough space for all its fields and another copy of itself.

Finally, what is the recommended way to solve this problem?



Write a class instead of a struct. Then the value of the variable will be a reference to the instance, not the data. This is how you end up with something close to a "pointer" in C #. (Pointers and links are different, mind you.)

I suggest you read my article on Value Types and Reference Types for more information - this is an absolutely essential topic to understand in C #.

+6


source


It is not a pointer; this is the actual value of the inline struct

.
The whole point struct

is that they are (almost) never pointers.



You should use instead class

.

+10


source


The Backpointer must exist before the Backpointer is created, because you cannot have a Backpointer without another Backpointer (which would then need another Backpointer and then on and on). You simply cannot create a Backpointer based on how you created it, because, as a structure, a Backpointer can never be null.

In other words, it is not possible to create a Backpointer with this code. The compiler knows this, and so it forces you to do something that will work logically.

+3


source


Structures are stored by value. In this case, your structure contains another instance of the same structure. This structure contains another structure, and so on. Therefore it is not possible. It's like every person in the world should have 1 child. It's impossible.

What you need to use is a class. Classes are stored by reference, which means that it does not store the class internally, it only stores a reference to that class.

0


source


The CLR is struct

by definition a value of a type . This means the compiler must know the exact location of the type in your context. However, it can't know how to layout a type that contains an instance of itself - does that sound reasonable? Change the struct to a class (which makes yours a BackPointer

reference type ) and you can see it works out of the box. The reason is that an instance of any reference type always has the same layout - it's basically just a "pointer" to some location on the managed heap. I highly recommend reading a little about the basics of the C # or CLI type system.

0


source







All Articles