I read all the questions related to this topic, and they all give reasons why a default constructor on a struct
is not available in C#, but I have not yet found anyone who suggests a general course of action when confronted with this situation.
The obvious solution is to simply convert the struct
to a class
and deal with the consequences.
Are there other options to keep it as a struct
?
I ran into this situation with one of our internal commerce API objects. The designer converted it from a class
to a struct
, and now the default constructor (which was private before) leaves the object in an invalid state.
I thought that if we're going to keep the object as a struct
, a mechanism for checking the validity of the state should be introduced (something like an IsValid
property). I was met with much resistance, and an explanation of "whoever uses the API should not use the default constructor," a comment which certainly raised my eyebrows. (Note: the object in question is constructed "properly" through static factory methods, and all other constructors are internal
.)
Is everyone simply converting their struct
s to class
es in this situation without a second thought?
Edit: I would like to see some suggestions about how to keep this type of object as a struct
-- the object in question above is much better suited as a struct
than as a class
.
For a struct
, you design the type so the default constructed instance (fields all zero) is a valid state. You don't [shall not] arbitrarily use struct
instead of class
without a good reason - there's nothing wrong with using an immutable reference type.
My suggestions:
struct
is valid (a [real] profiler revealed significant performance problems resulting from heavy allocation of a very lightweight object).struct
outside the wrapper (private nested type). That way you can easily document and verify proper use of the constrained type requirements.The reason for this is that a struct (an instance of System.ValueType) is treated specially by the CLR: it is initialized with all the fields being 0 (or default). You don't really even need to create one - just declare it. This is why default constructors are required.
You can get around this in two ways:
Changing the struct to a class can have some very subtle consequences (in terms of memory usage and object identity which come up more in a multithreaded environment), and non-so-subtle but hard to debug NullReferenceExceptions for uninitialized objects.
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