【发布时间】:2015-05-14 08:43:34
【问题描述】:
我正在使用C# 4.0、Asp.Net。我对在我创建的自定义缓存中正确构建 readonly 结构有疑问。
详情(摘要):
我的 CacheManager 类(单例)使用现有 MemoryCache 类的实例作为参数,并包含一些有用的方法来处理我的自定义缓存中的对象生命周期等补充内容。
那个经理处理一个简单的CachableObject,它接受三个变量:
-
object DateTime-
int(持续时间)
总之,我的自定义缓存管理器在有限的时间内存储objects,以保护我的数据库免受频繁的大查询。
最近,我尝试:
- 从缓存中取回一个对象(即:存储在密钥
-MyList下) - 将其转换回复杂对象列表
- 翻译了每个复杂对象的一些属性的内容
- 再次将新翻译的对象列表存储在缓存中,(在另一个键
-MyTranslatedList下)
问题:
在我的测试过程中,在我看来,存储在缓存中的两个列表(原始列表和翻译列表)都引用了相同的底层对象。因此,一旦翻译,这些对象实际上在两个列表中都被翻译了。
由于每个列表都只有对对象的引用,这是一种完全正常的行为,也是我犯的一个愚蠢的错误。
问题:
正如你现在很容易猜到的那样,我想保护我自己和我的单例的其他用户,以免出现这种错误。
我想插入(或存储或获取)任何类型的对象(或复杂对象的列表),因此任何通过缓存获取它们的人都无法更改它们。我希望我的缓存中的数据是只读的(并且 deeply 只读)以避免出现这种问题。我希望任何人在开始使用缓存中存储的数据之前拥有创建一个深层副本(或者更好的是,获得一个)。
到目前为止我尝试了什么:
我试图将object 设为只读。它没有按预期工作。
由于我经常存储复杂对象的列表,因此我发现了返回 IReadOnlyCollection 的 AsReadOnly 方法,但这会阻止我更改列表(添加、删除),但它并不能保护那些在列表中。
我希望我的解释有点可以理解 :) 有没有一种巧妙的方法来处理这种情况?
【问题讨论】:
-
不,如果某人引用了某个对象,则无法阻止他更改该对象。如果实在不想更改对象,可以将它们设为
ICloneable或为它们提供只读接口。 -
@Sameer 谢谢你的回答 Sameer。到目前为止,据我了解,不可变集合提供了对不会更改的列表的线程安全访问。它不保证列表中的元素不会改变...你知道我的意思吗?
-
@Spo1ler 感谢您的回答 Spo1ler。嗯,问题在于,由于我将随机对象放入缓存中,因此我无法更改所有对象以使其可 ICloneable。有意义吗?
标签: c# list caching readonly readonly-collection