I have a case where a struct may be preferable to a class:
- contains 3 bools
- is immutable
- is never boxed
However, I would like to add a number of properties with only get access, which provide combinations of the mentioned 3 bools. For example, the bools are “Same”, “Forward”, and “Backward”. Properties would be “All”, “None”, “UniDirectional”, “BiDirectional”, and so forth, which can be determined from the former 3.
Will these properties increase the size of each instance of the struct on the stack, and thus make a class more appropriate? Or will it not affect the choice?
Short answer:
No, they do not.
Long answer:
No, they do not; but…
Properties themselves are just regular methods but dressed in field-like syntax. Because methods only exist in one location in memory (because they’re the same for every object of that type) they do not affect the size of each instance. Note that virtual methods (including virtual properties) muddy this a bit as adding a new virtual method will increase the size of the vtable, however a vtable only exists once for each class; but this is moot because structs don’t have vtables in .NET (in C++ they do, but that’s because structs and classes are semantically identical).
“Properties” can increase the memory size of a struct type, but only if the person who wrote them is unfamilar with “auto-properties”. C# 3.0 introduced automatically-implemented properties (or “auto-properties” for short), where a hidden field is created by the compiler for trivial getter/setter properties. The syntax is
public PropertyName { get; set; }.Back on-topic: only instance member fields affect the size of a struct, unless you have overlapping fields when using a custom StructLayout (which is how you create
unions in C#). Note that static members do not affect the size of an instance, however in VB theStatickeyword, when used for a local variable, can affect instance size (despite the same word, “static”, local variables markedStaticin VB are not in class static state).Finally, note that in .NET there are overheads associated with values, but these are inherent in the “Managed” nature of .NET, however they don’t apply to structs used in interop scenarios (i.e. pointer arithmetic and
sizeofall work as they would under C/C++).