Originally in my heap class,
null was a special value. The type of the heap was always
object and so this made sense. Either the contained item was a reference type and null was a natural value to store for no item, or it was a boxed value type (which performed poorly but worked fine). When moving to a generic implementation, you've got to think about how dependent you are on these kind of special values. If you don't have a lot of reliance on them then the approach I took may work well for you. I simply substituted
When the top object was extracted from the heap, I was simply using
null to break the reference from the heap to the object it previously contained and so was holding alive. For a reference type, the default value is null anyway, so this still works. For value types, it doesn't really matter what the value used is as we're not holding anything up as far as garbage collection is concerned.
If you're using
null as a special value in your APIs then you're in for more work. For instance, you might previously have returned null from a "Find" method to indicate that no value was found. If you allow your collection to take any generic parameter, then null is no longer a valid return value for that method if the generic type is a value type, so you're stuck. There are a couple of routes you could go down here:
If you don't need to be able to support value types, you could constrain your generic parameter to be a reference type by using the
where T : class technique. EricGu has an article on the topic here.
You can alter the "Find" method to separate the "found" boolean value from the "what was found" value of type "T". This is the approach taken by the Dictionary
null - you always pay some price for progress.