EDIT I should've started with this example in the 1st place:
Think about enums. Every enum we write automatically extends Enum
, which is a class.
Hence, value types we write extend a class written by the .NET team which is a reference type.
You can split the world of types in two ways:
- whether they contain the
null
value or not
- whether they are value types or not
All combinations are possible in theory. If I'm not mistaking, in C# at least, the combination of reference types which cannot be null
yields an empty set. There is no example for that combination.
Basically all other 3 combinations are possible:
- types which can be null and are value types
- types which cannot be null and are value types
- types which can be null and are reference types
The nature of being either a value type or a reference type has nothing to do with null
(at least in the way languages should be designed and used, not in the way of the actual engineering details underneath).
Value types are types which cause assignments between variables, parameters and fields to do full cloning of the instance.
Reference types are types which don't do that.
That has basically nothing to do with null
or with the type of memory which is occupied by the instances (be it stack, heap or something else).