ASP.NET无法缓存空值

任何人都可以解释为什么你不能将空对象插入ASP.NET缓存?

string exampleItem = null; HttpRuntime.Cache.Insert("EXAMPLE_KEY", exampleItem, Nothing, DateTime.Now.AddHours(1), System.Web.Caching.Cache.NoSlidingExpiration); 

exception错误消息指出“value”对象不能为null。 在我的应用程序中,有充分的理由说明为什么我们想要在缓存中存储空值。

底层Cache可能是HashtableDictionary ,其getter不区分该键的值或该键的空值。

 Hashtable table = new Hashtable(); object x = table["foo"]; table.Add("foo", null); object y = table["foo"]; Console.WriteLine(x == y); // prints 'True' 

考虑使用占位符“null”项,类似于DbNull.Value

为了澄清Michael Petrotta接受的答案(我害怕评论太长了),CacheInternal(CacheSingle和CacheMultiple,后者仅管理前者的多个实例)的具体实现,这是内部使用的公共Cache类型支持其Get,Add,Insert等方法,确实依赖HashTable进行存储。 但是,HashTable中的特定键是否存在或不存在任何问题,因为本机(缓存)值不会直接存储在HashTable中。 相反,HashTable填充了唯一的CacheEntry对象,这些对象包装缓存的键和值(CacheEntry实际上派生自CacheKey,添加基于对象的Value属性等等;非null值要求可以在其构造函数中找到)。

基于我对代码的阅读,作者没有明显的技术原因要求非空的CacheEntry.Value,除了公共Cache对象不公开Contains-或Exists-类型的方法,当然也没有不公开内部底层CacheEntry对象,它只返回CacheEntry值。 因此,根据Michael的回答,在不强制值为非null的情况下,Cache对象用户无法知道特定键值是否存在。 这也是可能的,但需要更多的代码读取才能确定,内部采用的相当复杂的方法来管理缓存的对象依赖关系,过期,事件和HashTable条目的就地更新可能在某种程度上依赖于值不为空。

作为一种可能的替代方法或解决方法,您可以改为存储对象而不是您的值。 例如(假设您的值是一个字符串,但它可能是通用的)

 public class CacheItemWrapper { public string Value { get; set; } } 

 cache.Insert(cacheKey, new CacheItemWrapper { Value = null }, ...); 

这样你永远不会插入null。 要获取值,只需从包装器中提取它:

 var val = cache.Get(cacheKey); if (val != null) return val.Value; 

(这完全不是我的头脑,所以对任何愚蠢的错别道歉。)