views:

432

answers:

6

References in C# are quite similar to those on C++, except that they are garbage collected.

Why is it then so difficult for the C# compiler to support the following:

  1. Members functions marked const.
  2. References to data types (other than string) marked const, through which only const member functions can be called ?

I believe it would be really useful if C# supported this. For one, it'll really help the seemingly widespread gay abandon with which C# programmers return naked references to private data (at least that's what I've seen at my workplace).

Or is there already something equivalent in C# which I'm missing? (I know about the readonly and const keywords, but they don't really serve the above purpose)

A: 

The question is, do we need constness in C#?

  1. I'm pretty sure that the JITter knows that the given method is not going to affect the object itself and performs corresponding optimizations automagically. (maybe by emitting call instead of callvirt ?)

  2. I'm not sure we need those, since most of the pros of constness are performance related, you end up at the point 1.

Besides that, C# has the readonly keyword.

arul
I disagree with your claim that "most of the pros of constness are performance related" - I'd say most are correctness and maintainability related.
Jon Skeet
It's not for the convenience of the JITter, but for the programmer. In C++, if I'm trying alter a const object, the compiler gives me a error. So, for example, I can return const references from my methods. In C# everybody seems to be returning references that anybody outside can change. Dangerous!
Frederick
@Frederick: Exactly :)
Jon Skeet
+13  A: 

I suspect there are some practical reasons, and some theoretical reasons:

  • Should the constness apply to the object or the reference? If it's in the reference, should this be compile-time only, or as a bit within the reference itself? Can something else which has a non-const reference to the same object fiddle with it under the hood?
  • Would you want to be able to cast it away as you can in C++? That doesn't sound very much like something you'd want on a managed platform... but what about all those times where it makes sense in C++?
  • Syntax gets tricky (IMO) when you have more than one type involved in a declaration - think arrays, generics etc. It can become hard to work out exactly which bit is const.
  • If you can't cast it away, everyone has to get it right. In other words, both the .NET framework types and any other 3rd party libraries you use all have to do the right thing, or you're left with nasty situations where your code can't do the right thing because of a subtle problem with constness.

There's a big one in terms of why it can't be supported now though:

  • Backwards compatibility: there's no way all libraries would be correctly migrated to it, making it pretty much useless :(

I agree it would be useful to have some sort of constness indicator, but I can't see it happening, I'm afraid.

EDIT: There's been an argument about this raging in the Java community for ages. There's rather a lot of commentary on the relevant bug which you may find interesting.

Jon Skeet
Thanks Jon. That's illuminating.
Frederick
A: 

Duplicate Question, can someone please close?

Binary Worrier
+6  A: 

As Jon already covered (of course) const correctness is not as simple as it might appear. C++ does it one way. D does it another (arguably more correct/ useful) way. C# flirts with it but doesn't do anything more daring, as you have discovered (and likely never well, as Jon well covered again).

That said, I believe that many of Jon's "theoretical reasons" are resolved in D's model.

In D (2.0), const works much like C++, except that it is fully transitive (so const applied to a pointer would apply to the object pointed to, any members of that object, any pointers that object had, objects they pointed to etc) - but it is explicit that this only applies from the variable that you have declared const (so if you already have a non-const object and you take a const pointer to it, the non-const variable can still mutate the state).

D introduces another keyword - invariant - which applies to the object itself. This means that nothing can ever change the state once initialised.

The beauty of this arrangement is that a const method can accept both const and invariant objects. Since invariant objects are the bread and butter of the functional world, and const method can be marked as "pure" in the functional sense - even though it may be used with mutable objects.

Getting back on track - I think it's the case that we're only now (latter half of the naughties) understanding how best to use const (and invariant). .Net was originally defined when things were more hazy, so didn't commit to too much - and now it's too late to retrofit.

I'd love to see a port of D run on the .Net VM, though :-)

Phil Nash
+3  A: 

Mr. Heljsberg, the designer of the C# language has already answered this question:

http://www.artima.com/intv/choicesP.html

DrJokepu
Interesting, I hadn't seen that. I think with the functional perspective (as brought out in my reply) it makes any difficulty worth it, though.
Phil Nash
+2  A: 

I wouldn't be surprised if immutable types were added to a future version of C#. There have already been moves in that direction with C# 3.0.

Anonymous types, for example, are immutable.

I think, as a result of extensions designed to embrace parallelism, you will be likely to see immutability pop up more and more.

Scott Wisniewski