具有丰富类型的C#中的const正确性

时间:2012-07-24 21:11:16

标签: c# .net const const-correctness readonly

来自C ++背景并尝试学习C#,我遇到的最令人沮丧的语言遗漏之一是等同于const关键字。

所以,我一直试图找到一种可以用来在C#中实现const正确性的模式。

This answer有一个有趣的建议:为所有类型创建一个只读界面。但正如Matt Cruikshank在评论中指出的那样,如果你的班级有收藏品或其他丰富类型,这就成了问题。特别是如果您无法控制类型,并且无法使其实现只读接口。

是否存在可以处理丰富类型和集合的任何模式或解决方案,或者我们是否强制在C#中进行复制?是否最好完全放弃C#中的const正确性?

1 个答案:

答案 0 :(得分:7)

你能在C#中获得不变性吗?当然,如果你为它设计。您可以使用接口创建创造性的东西,等等,只显示get属性,而不显示任何可变方法。

那就是说,请记住,没有任何东西可以阻止狡猾的用户将其转换回实际类型(当然,可以说是C ++,你可以抛弃常量)。

ISomeReadOnlyInterface readOnly = new SomeFullObject();

// hah, take that read-only interface!
((SomeFullObject)readOnly).SomeMutatingMethod();

与收藏品相同。即使你返回一个ReadOnlyCollection(它可以阻止对集合本身的变异行为),集合中的数据仍然是可变的(只要类型允许它当然)。

所以我担心这里真的没有简单的答案。没有“flip-a-switch”const可以为您提供C ++的功能。

这取决于你,你可以:

  • 将您的类型设计为不可变的并返回迭代器(或其他只读序列)而不是可变集合。
  • 每次都要返回新的副本,这样如果他们改变它们就没什么大不了的了。
  • 只需返回实际数据并将篡改行为保留为“未定义”。
  • 等...

后者是像Dictionary<TKey, TValue>这样的集合。没有什么可以说你不能把密钥类型变成一个可变类型(但是如果你这样做会有祸害),并且MSDN非常清楚,如果你改变密钥的方式是它的哈希代码改变了,那就在你自己的脖子上...

对于我自己的工作,我倾向于保持简单,除非实际上有一个大问题,我的课程可能会以一种会导致副作用的方式改变。例如,如果我将Web服务结果存储在缓存中,我将返回缓存项的副本,以便在用户修改结果时不会无意中修改缓存的值。

所以,很长一段时间,我不会担心你返回的每个类型的const-correctness,这太过分了。我只担心你返回的东西,如果改变了,可能会给其他用户带来副作用。