8

Coming from a C++ background and trying to learn C#, one of the most frustrating language omissions that I've come across is an equivalent to the const keyword.

So, I have been attempting to settle on a pattern that I can use to achieve const correctness in C#.

This answer has an interesting suggestion: create a read only interface for all of your types. But as Matt Cruikshank pointed out in the comments, this becomes problematic if your class has collections or other rich types. Particularly if you do not have control over the type, and can't make it implement a read-only interface.

Do any patterns or solutions exist that can handle rich types and collections, or are we forced in C# to simply make copies? Is it better to just give up on const correctness in C# altogether?

4

1 回答 1

7

你能在 C# 中获得不变性吗?当然,如果你为它设计。你可以用接口做一些创造性的事情,等等,只公开get属性而不公开可变方法。

也就是说,请记住,没有什么可以阻止狡猾的用户将其转换回实际类型(当然,C++ 也可以这样说,你可以放弃 const-ness)。

ISomeReadOnlyInterface readOnly = new SomeFullObject();

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

与集合相同。即使您返回 ReadOnlyCollection(它可以防止集合本身发生变异行为),集合中的数据仍然是可变的(当然,只要类型允许)。

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

这完全取决于您,您可以:

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

后者是集合喜欢Dictionary<TKey, TValue>做的事情。没有什么说您不能将密钥类型设为可变类型(但如果您这样做会很糟糕),而且 MSDN 很清楚,如果您更改密钥以使其哈希码发生变化,那么它就在您自己的脖子上...

对于我自己的工作,我倾向于保持简单,除非真的很担心我的课程可能会以一种会导致副作用的方式改变。例如,如果我将 Web 服务结果存储在缓存中,我将返回缓存项的副本,这样如果用户修改结果,他们就不会无意中修改缓存值。

因此,总而言之,我不会担心您返回的每种类型的 const 正确性,这太过分了。我只担心您返回的东西,如果更改,可能会对其他用户产生副作用。

于 2012-07-24T21:28:50.717 回答