I tried to create a ValueType.
I understand that creating a struct would help me.
I also tried to derive a type from System.ValueType which is an abstract class.
But I got a compiler error message
".. cannot derive from special class System.ValueType"
When I see the metadata of ValueType, it looks to be a regular abstract class. Any non sealed class should be derivable. But System.ValueType is not a sealed class.
-
What made it special?
-
Is it the C# compiler that senses it as special?
-
If so, is it recommended as a rule for compiler design? I mean is it part of Common Language Specification?
ValueType is a little white lie.
The built-in numeric types (int, long, byte), char, enums and structs are all value types.
This means that they have a different concepts of identity and equivalence to object types. If I do
x = yand x and y are reference types, then x and y now point to precisely the same object. However, if I dox = yand x and y are value types, then x and y are now two completely different objects that happen to be identical. (This is also reflected in==andEquals, though that can be overridden).(This is where people get sidetracked by talking about the stack and the heap, if they haven’t already, really that’s an implementation detail and while important, is not the point of the distinction between value and reference types).
Now, mostly this is all and good but one thing about reference types is that they all benefit from inheriting from System.Object. The value type int doesn’t really, and that’s good too as it’s much better in many ways that it just be four bytes of memory handled by the lovely CPU instructions that are so good at doing so. Still, it’s sometimes useful to be able to treat an int as if it also inherited from System.Object, and so you can.
Of course, this means that you may do things with int that only make sense to do on a System.Object, so when you do so the int is "boxed" and can then be "unboxed" again.
This is great, but what if we wanted to do something specific to value types? More to the point, what if the designers of the CLR did (in particular, they wanted a GetHashCode for value types that related to the value-based equivalence descibed above, rather than the identity-based equivalence that objects have)?
For this purpose we have ValueType. The system treats all value types as inheriting from this class, which in turn inherits from Object. Enum in turn inherits from value type and all enum types inherit from it, allowing some common functionality across all enums.
So, if you ever want to treat a superclass of all value types, use ValueType, but if you want to actually create a value type, create a struct or an enum as appropriate.
The Common Type System explanation:
The strangeness of ValueType is to allow the above to happen.