1

If I have a Struct with arrays of other structs, is this than still a value-based type? In detail what I don´t understand is, that usually structs are meant to be value-based, but arrays for example are reference-based, right? So is such a struct now value-based or reference-based? And what does this mean in case of multithreading?

To put this in a applicable context:

If I generate a struct instance (which contains arrays of structs) within a Thread, read it from another Thread and assign it there to a property, can I than change and reuse this newly assigned property without conflicting with the struct instance from the original thread?

Charlieface
  • 52,284
  • 6
  • 19
  • 43
  • A struct is a struct is a struct. The members of a struct are pointless concerning if the struct is a value-type. However the members of that said struct can be reference-types (e.g. an array of whatever). – MakePeaceGreatAgain Aug 01 '22 at 12:01
  • Does this answer your question? [Is int\[\] a reference type or a value type?](https://stackoverflow.com/questions/1533757/is-int-a-reference-type-or-a-value-type) – Charlieface Aug 01 '22 at 13:08

2 Answers2

3

A structure is a value type and a class is a reference type. That never changes.

If you have a local variable in a method in your code, when that code is executed, space is allocated for that variable on the stack. If that variable is a value type then the structure instance will be stored in the variable itself while, if the variable is a reference type, space will be allocated for the object on the heap and a reference to that object will be stored in the variable.

When an object is created, whether on the stack or the heap, that object contains its member variables. If the object is created on the stack then the member variables exist on the stack and if the object is created on the heap then the member variables exist on the heap. Whether those member variables exist on the stack or the heap, they still behave exactly as value types and reference types always do, i.e. the value type variables contain the objects and the reference type variables contain references to objects created on the heap.

If you have a structure with a member variable that is an array then the structure will behave like value types always do, i.e. the object will be stored in the variable, wherever that variable happens to be. The array field will contain a reference to an array created on the heap. If the array is of a value type then the array will contain the element objects themselves while an array that is of a reference type will contain references to objects stored elsewhere on the heap.

It's pretty simple really:

  • Local variables are stored on the stack.
  • Member variables are stored within the object, wherever that is stored.
  • Value type objects are stored in the variable, wherever that is stored.
  • Reference type objects are stored on the heap and a reference to them is stored in the variable, wherever that is stored.
user18387401
  • 2,514
  • 1
  • 3
  • 8
  • Thank you really much for the detailed explaination! So if the array consists out of value-type-elements, the array field will store its elements itself, which means struct a = struct b will copy the whole instance of struct b including all array elements from b to a and is threadsafe than right? – JJCodesFresh Aug 01 '22 at 13:03
  • @JJCodesFresh, this is repeating what's already been said but arrays are reference types so an array field in a structure contains a reference, so copying that structure just copies the reference, not the array. The copy will refer to the same one and only array object. – user18387401 Aug 01 '22 at 13:09
  • 1
    [The Stack Is An Implementation Detail](https://ericlippert.com/2009/04/27/the-stack-is-an-implementation-detail-part-one/) it's entirely irrelevant to the question of reference vs value types, which is concerned with pass-by-reference semantics. Or putting it another way: it's perfectly possible for an implementation to put all value-type variables on the heap also, and it's possible for reference-types that are known not to escape to be placed on the stack. – Charlieface Aug 01 '22 at 13:09
  • Ok thank you! I just wanted to make this sure, so its not threadsafe to just reference struct1 a = struct1 b; when struct1 contains a array. Therefore I need to perform a deep copy of the array in addition. Thanks! – JJCodesFresh Aug 01 '22 at 13:12
1

A struct is always value type. If you have an array of structs, the array will be a reference type but contain value types. If the struct contains arrays then the struct will be a value type that contains reference types.

In your multi-threading example, you would be creating a copy of the struct so would be able to change it on the other thread without worrying about the original being updated.

YungDeiza
  • 3,128
  • 1
  • 7
  • 32
  • Well, if is still actual, I have written a [package](https://www.nuget.org/packages/Fluentsoft.Generators) that implement array as value type. This kind of array can be placed inside any struct and will be part of the struct. – V Zabavnov Jun 30 '23 at 19:04