Why are we not forced to instantiate a struct, like when using a class?
Like a class, you can create an instance of a struct using the new keyword. You can either invoke the default parameterless constructor, which initializes all fields in the struct to their default values, or you can invoke a custom constructor.
When you create a struct object using the New operator, it gets created and the appropriate constructor is called. Unlike classes, structs can be instantiated without using the New operator. If the New operator is not used, the fields remain unassigned and the object cannot be used until all the fields are initialized.
A struct object can be created with or without the new operator, same as primitive type variables. Above, an object of the Coordinate structure is created using the new keyword.
Using designated initializers, a C99 feature which allows you to name members to be initialized, structure members can be initialized in any order, and any (single) member of a union can be initialized.
Why are we not forced to instantiate a struct with "new", like when using a class?
When you "new" a reference type, three things happen. First, the memory manager allocates space from long term storage. Second, a reference to that space is passed to the constructor, which initializes the instance. Third, that reference is passed back to the caller.
When you "new" a value type, three things happen. First, the memory manager allocates space from short term storage. Second, the constructor is passed a reference to the short term storage location. After the constructor runs, the value that was in the short-term storage location is copied to the storage location for the value, wherever that happens to be. Remember, variables of value type store the actual value.
(Note that the compiler is allowed to optimize these three steps into one step if the compiler can determine that doing so never exposes a partially-constructed struct to user code. That is, the compiler can generate code that simply passes a reference to the final storage location to the constructor, thereby saving one allocation and one copy.)
So now we can address your question, which you actually have asked backwards. It would be better to ask:
Why are we forced to allocate a class with "new", instead of simply being able to initialize the fields as with a struct?
You have to allocate a class with "new" because of those three things on the list. You need new memory allocated from the long-term storage and you need to pass a reference to that storage to the constructor. "new" is the operator that knows how to do that.
You don't have to call "new" on a struct because there is no need to allocate the "final" storage; the final storage already exists. The new value is going to go somewhere, and you already have obtained that storage by some other means. Value types do not need a new allocation; all they need is initialization. All you need to do is ensure that the storage is properly initialized, and you can often do that without calling a constructor. Doing so of course means that you run the risk of having a variable of value type that can be observed to be in a partially initialized state by user code.
Summing up: calling a ctor is optional for value types because no new memory needs to be allocated when initializing an instance of a value type and because skipping the constructor call means that you get to skip a short-term allocation and a copy. The price you pay for that performance gain is that user code can see a partially initialized structure.
The why is simply - because the spec says so. The how is a matter of ensuring that the entire block of memory is "definitely assigned", which means: assigning a value to each field of the struct. However, this requires 2 nasty things:
so in most best-practice cases, you do need to use the new(...)
syntax, to invoke the constructor (or to zero-the memory, for the parameterless constructor) for the type correctly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With