Const correctness in C# with rich types

2019-04-23 09:16发布

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?

1条回答
相关推荐>>
2楼-- · 2019-04-23 09:43

Can you get immutability in C#? Sure, if you design for it. You can do creative things with interfaces, and so on, to only expose the get of properties and none of the mutable methods.

That said, keep in mind there is nothing that prevents a crafty user from casting it back to the actual type (of course, same could be said of C++, you can cast away const-ness).

ISomeReadOnlyInterface readOnly = new SomeFullObject();

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

Same with collections. Even if you return a ReadOnlyCollection (which prevents mutating behaviors on the collection itself) the data in the collection is still mutable (as long as the type allows it of course).

So I'm afraid there's really no simple answer here. There's no "flip-a-switch" const that gives you what C++ does.

It's really up to you, you can:

  • Design your types to be immutable and return iterators (or other read only sequences) instead of mutable collections.
  • Return new copies each time so that if they alter them it's no biggie.
  • Just return the actual data and leave tampering behavior as "undefined".
  • etc...

The latter is what collections like Dictionary<TKey, TValue> do. There's nothing that says you can't make the key type a mutable type (but woe if you do), and the MSDN is pretty clear that if you alter the key in such a way that it's hash code changes, it's on your own neck...

For my own work, I tend to keep it simple unless there is actually a big concern my class may be altered in a way that would cause side-effects. For example, if I'm storing web service results in a cache, I'll return a copy of the cached item instead so that if a user modifies the result they won't inadvertently modify the cached value.

So, long and the short of it is that I wouldn't worry about const-correctness of every type you return, that's just way too much. I'd only worry about things that you return that, if altered, could create a side-effect to other users.

查看更多
登录 后发表回答