In itself a null pointer will take up 4 or 8 bytes, depending on whether it is running as 32-bit or 64-bit, as you've surmised.
There can be more than this in a given collection. The implementation of Dictionary<TKey, TValue>
uses both an array of Entry<TKey, TValue>
structures, which contains two int
s as well as the key and value, and also an array of integers used in indexing into that array. Hence even if there was no "growing room" (and there generally is) each entry would need 20bytes or 24bytes of memory (rather than just the 8 or 12 entailed by the size of the key and value), on top of the overhead for the dictionary itself (including the overhead of each array).
Other implementations and other collections will have other overheads. They may not even store a null
for a null entry. null
can be a useful way of indicating a value has not been written in which case a special value will indicate an actual value of null
(particularly useful in lock-free dictionary implementations, where it can be useful to distinguish between not just an unset and set value, but between an unset, set, and partially set value).
All you can really say is that setting adding a value of null
A) takes up some memory and B) does not take up the memory that with a non-null value would be taken up by the object itself. Even B) doesn't really hold, since if that object was also stored elsewhere, then there's no extra memory cost in having another reference elsewhere, beyond that of the reference itself, which makes the real cost of it the same as storing null
.