Чтобы немного разъяснить принятый ответ Майкла Петротты (боюсь, слишком долго для комментария), конкретные реализации CacheInternal (CacheSingle и CacheMultiple, последний из которых просто управляет несколькими экземплярами первого), что является используется внутренне общедоступным типом Cache для поддержки его методов Get, Add, Insert и т. д., для хранения используется HashTable. Однако никогда не возникает вопроса о том, существует или нет значение для конкретного ключа в HashTable, потому что собственные (кэшированные) значения не хранятся в HashTable напрямую. Вместо этого HashTable заполняется уникальными объектами CacheEntry, которые обертывают кэшированные ключи и значения (CacheEntry фактически наследуется от CacheKey, добавляя, среди прочего, свойство Object-Based Value; требование ненулевого значения можно найти в его конструкторе).
Исходя из моего прочтения кода, у авторов нет очевидных технических причин, по которым требуется CacheEntry.Value, отличный от NULL, за исключением того, что открытый объект Cache не предоставляет метод типа Contains- или Exists, и конечно, не раскрывает внутренние базовые объекты CacheEntry, он только возвращает значения CacheEntry. Таким образом, согласно ответу Михаэля, не заставляя значения быть ненулевыми, пользователи объекта Cache не смогут узнать, существует ли конкретное значение ключа. Это также возможно, но потребует больше чтения кода, чтобы точно знать, что довольно сложный подход, применяемый внутри компании для управления зависимостями кэшированных объектов, истечениями, событиями и обновлениями на месте записей HashTable, может в некоторой степени зависеть от значений будучи ненулевым.