Introduction - Why Use Structs Anyway?
Why struct
anyway?
We all like C#'s struct
s very much [an idea alien to Java, apart from primitive types]. Struct
s, when they do not have to be boxed frequently, provide a nice way to handle relatively small and short lived data.
Allocations and deallocations of value types are in general cheaper than allocations and deallocations of reference types, since struct
s are allocated either on the stack or inline in containing types and deallocated when the stack unwinds or when their containing type gets deallocated, while reference types are allocated on the heap and garbage-collected.
Hmmm, It Won't Let Me Inherit....
Object Oriented Programming gives us the ability to do quite a lot of stuff, and the basic concept in OO is of course the inheritance.
Many of us have tried at one point to inherit a struct
, only to find out that C# does not allow it.
Consider this code for example:
struct MyDateTime : DateTime
{
double SecondsFromMyBirthday { get; private set; }
}
struct Point
{
int x, y;
}
struct Point3D : Point
{
int z;
}
An honest programmer wishes to expand the DateTime
struct, why shouldn't she?
This code will produce the compile time error: Type 'DateTime' in interface list is not an interface (the reason for this specific error message is the fact that since inheritance is not allowed the compiler expects only an interface after the colon symbol - it does not even take a misuse of inheritance into account...)
If the struct
would be replaced to class, the compile time error will produce: 'MyDateTime
': cannot derive from sealed type 'System.DateTime
'
We understand then, that System.DateTime
is (implicitly) sealed
. But why?
Note: Actually the fact is that all struct types implicitly inherit from the class System.ValueType
, which, in turn, inherits from class object.
Note: Although a Struct cannot be inherited, it can implement an interface.
The Answer
A struct
has a fixed size allocated already on the stack.
Now consider the Point
/ Point3D
example above which seems like a nice innocent case. Consider the following line of code:
p2d = p3d;
What should happen on the assignment line then? A memory expansion of p2d
on the stack to support the assignment?
Furthermore - struct
s, being a value type of course, do not use references (unless boxed), this would make polymorphism somewhat meaningless since there is no indirection via a reference pointer.
Also, consider the case of arrays - arrays of value types are stored "inline" (for performance and garbage collection reasons). If we use a struct
without knowing it is actually a "derived struct
", it will cause memory corruption.
In conclusion - we've seen why it is highly unreasonable for .NET to allow inheritance of a struct
. The good news is that you can always inherit ... well ... a class!