const


Z

Zach

this is a rant. I want constness in C# the same way it is implemented
in C++. I'm not here to argue that C++ is superior to C# or C# sucks
or anything like that. They're both awesome languages when used for
the problem domains they excel at.

One thing C++ gets hands down correct though is constness. It would be
used something like this:

class A
{
public void DoSomethingUseful(const B parameter)
{
parameter.Member = 5; //Compilation fails
}
}

class B
{
public int Member = 0;
}

class Main
{
public static void Main(string[] args)
{
A a = new A();
B b = new B();

a.DoSomethingUseful(b);
}
}


This doesn't change the emitted IL at all. It's strictly a hint to
the compiler to throw an error when a violation is encountered. It is
immensely frustrating that with the current state of the language,
under no circumstances do I ever have any kind of guarantee about the
state of an object after invoking a function which takes an instance
of that object as an argument.

Take a collection for example. Collections should never need to
modify the state of the underlying object if you're simply asking for
the length. I know this is a blanket statement and I'm making it for
all past, current, and future collections that may ever exist, but
still, there is always "mutable" for the rare and crazy cases where
you want to break the law. In any case, why can't the Length()
function let the caller know as part of its signature that it plays
nice? Then, if I implement some serializer that serializes lists by
taking a reference to the list as an argument, that function can also
document that it plays nicely on lists by specifying the argument
const.

For anyone who's never used C++, I can't even begin to explain how
useful this is. But take my word that it results in better code. Not
better code than C#, just better code than it would if const didn't
exist.

Has anyone ever seen any rationale for why the language designers
opted not to add 'const' qualifiers?
 
Ad

Advertisements

P

Peter Duniho

Zach said:
this is a rant. I want constness in C# the same way it is implemented
in C++.

Well, you can't have it.
I'm not here to argue that C++ is superior to C# or C# sucks
or anything like that.

Of course you are. You are at the very least making that statement with
respect to a specific feature.
They're both awesome languages when used for
the problem domains they excel at.

Then use them for the problem domains they excel at. Why the rant?
One thing C++ gets hands down correct though is constness.

There is quite a lot of debate on that question, and plenty of arguments
(and those who would make those arguments) against your claim. It's far
from "hands down".
[...] It is
immensely frustrating that with the current state of the language,
under no circumstances do I ever have any kind of guarantee about the
state of an object after invoking a function which takes an instance
of that object as an argument.

Baloney. Just implement your objects as immutable objects. That is the
proper C# idiom to replace "const", and frankly it works a lot better
than "const" ever did or will. You can't cast away immutability.

It's true that C# could do more to help _implement_ immutable objects,
but the fact is that you can get all of the benefit of immutable objects
without that help.
Take a collection for example. Collections should never need to
modify the state of the underlying object if you're simply asking for
the length.

If you like, you can create collections that never modify the state of
the underlying object, ever.
I know this is a blanket statement and I'm making it for
all past, current, and future collections that may ever exist, but
still, there is always "mutable" for the rare and crazy cases where
you want to break the law. In any case, why can't the Length()
function let the caller know as part of its signature that it plays
nice? Then, if I implement some serializer that serializes lists by
taking a reference to the list as an argument, that function can also
document that it plays nicely on lists by specifying the argument
const.

How does that help you? How does it make your code better when you are
implementing a serializer to be able to specify a reference to an object
being serialized as "const"? Was there ever any real risk that your
serializer would actually _modify_ the object being serialized? Really?
Of all the bugs you've caused, how often does that really come up?

Accidental mutation of objects has never been a significant class of
bugs. On the other hand, _intentional_ mutation of objects that should
never have been mutated in the first place is, and this is solved only
by making object immutable, so people can't write code mutating them in
situations when they shouldn't be mutated.
For anyone who's never used C++, I can't even begin to explain how
useful this is.

I've used C++. I've used C++ longer than I've used C#. The "const"
keyword wasn't really that useful, and created all sorts of maintenance
headaches as you either eventually had to cast it away, or add it to
everything, just to get the program to compile.
But take my word that it results in better code. Not
better code than C#, just better code than it would if const didn't
exist.

I disagree, and I suggest no one just take your word for it. There's
plenty of discussion one can actually _read_ on the topic, and of course
getting some first-hand experience is an excellent way to explore the
question too.
Has anyone ever seen any rationale for why the language designers
opted not to add 'const' qualifiers?

Not per se. But given that it's not really needed, and given that
there's a general philosophy to add to the language only those things
that produce real value, it's not surprising to me it's not present.

Pete
 
Z

Zach

Of course you are.  You are at the very least making that statement with
respect to a specific feature.
Actually, no I'm not. I mention C++ specifically because it is the
most widely used language (so that people can actually relate to the
discussion) in which it is present. But I know that once C++ is
mentioned on a C# forum it automatically turns into a flame war /
pissing contest regardless of the OP's intention, so I put this
disclaimer in here simply to fend off such discussions.

Then use them for the problem domains they excel at.  Why the rant?

I do. But const isn't specific to any problem domain, it's a general
design aid. Similar concepts are even present in visual design tools
that transcend any particular programming language and exist simply to
model problem domains in object oriented terms..

There is quite a lot of debate on that question, and plenty of arguments
(and those who would make those arguments) against your claim.  It's far
from "hands down".
Where is the debate going on (aside from here)? I couldn't find much
of any substance, so if you have any relevant links I'd certainly be
interested in seeing it. Particularly any comments by language
designers.

[...] It is
immensely frustrating that with the current state of the language,
under no circumstances do I ever have any kind of guarantee about the
state of an object after invoking a function which takes an instance
of that object as an argument.

Baloney.  Just implement your objects as immutable objects.  That is the
proper C# idiom to replace "const", and frankly it works a lot better
than "const" ever did or will.  You can't cast away immutability.
Because I don't want the object to *always* be immutable. Being able
for object X to assert that it must never be mutated is only half the
battle.. The other half is allowing function Y to inform the *caller*
that X *will not* mutated. That is the whole point.

It's true that C# could do more to help _implement_ immutable objects,
but the fact is that you can get all of the benefit of immutable objects
without that help.


If you like, you can create collections that never modify the state of
the underlying object, ever.
So I have to create entirely new classes to wrap existing
functionality that for all intents and purposes works perfectly? What
do you propose, making an ImmutableList<T> that's constructible from
an IList<T>, and then throw exceptions in the mutator functions?
That's completely ridiculous, not to mention a lot of code for
something that could be solved actually with 0 additional lines of
code, just an additional keyword on 2 lines. Or should I design a
completely new collection that isn't even compatible with the current
generic collection interfaces and just re-implement all the actual
functionality of implementing a list on my own.

Besides, you're missing the point. The point is about *granularity*.
I don't want a collection that never modifies the state of the
underlying object. I want a collection that can tell you *when* it
modifies the state of the underlying object and when it doesn't.
That's it. The only purpose is to have the compiler find more bugs
for you. By going through all these hoops you're proposing, you're
probably typing enough code to actually *introduce* more bugs and
essentially negate any possible benefit.



How does that help you?  How does it make your code better when you are
implementing a serializer to be able to specify a reference to an object
being serialized as "const"?  Was there ever any real risk that your
serializer would actually _modify_ the object being serialized?  Really?
  Of all the bugs you've caused, how often does that really come up?

If the serializer is some object that's not written by me, then who
knows? For a language that's supposed to be "safe", you would think
that the fewer assumptions you could make about 3rd party code the
better.

Bottom line is that it has virtually no downsides, and benefits that
while to you may seem negligible since I guess you aren't too familiar
with const-correctness (more on this later), actually are hugely
beneficial.

Accidental mutation of objects has never been a significant class of
bugs.  On the other hand, _intentional_ mutation of objects that should
never have been mutated in the first place is, and this is solved only
by making object immutable, so people can't write code mutating them in
situations when they shouldn't be mutated.

This is exactly my point! Except why limit yourself to only being
able to specify immutability at the class level? In fact, const
allows you to specify immutability at any level of granularity you
desire. Including: class level, instance level, method level, field
level.

Furthermore, it provides a distinction between immutability of use (I
can't modify you) vs immutability of self (you can't modify me). You
already agree immutability is useful, so I can't understand how a more
flexible way of specifying immutability that is a strict superset of
what you propose could be less useful.

I've used C++.  I've used C++ longer than I've used C#.  The "const"
keyword wasn't really that useful, and created all sorts of maintenance
headaches as you either eventually had to cast it away, or add it to
everything, just to get the program to compile.
I've been in this situation too. And then I learned that if you have
to cast away, you're probably doing it wrong. The maintenance
headaches are due to trying to incorporate const-correctness into pre-
existing systems that weren't designed from the ground up with const-
correctness in mind. That's a recipe for disaster, and should not be
done without care. Taken into consideration from the ground up, it's
very easy to do it correctly.
I disagree, and I suggest no one just take your word for it.  There's
plenty of discussion one can actually _read_ on the topic, and of course
getting some first-hand experience is an excellent way to explore the
question too.
No offense, but this is coming from the person who said that it
creates maintenance nightmares and you had to cast it away all the
time just to get the program to compile. So you really were just
doing it wrong. Although if you have links to this wealth of debate
that you claim exists by people who actually do have a lot of
experience with both sides, I'd be more than interested.

Not per se.  But given that it's not really needed, and given that
there's a general philosophy to add to the language only those things
that produce real value, it's not surprising to me it's not present.
It's also no surprise that someone who doesn't fully understand how to
correctly use something would be inclined to believe that it's not
very useful.


Zach
 
P

Peter Duniho

Zach said:
Actually, no I'm not.

Actually, yes you are.

You specifically claim that "const" is something "C++ gets hand down
correct". The implication is that C# doesn't. If saying that C# is
incorrect and C++ is correct isn't a clear statement that C++ is
superior to C#, I don't know what would be.

The rest of your post reads like the usual religious-war stuff: you
presuppose the superiority, and then use that supposition as "proof"
that someone with a counter-argument must just not understand the
superior feature.

Whatever. Fact is, you aren't going to get this in C#. If you want
"const", go use a different language.

As for the discussion on the topic by others, there's this great
Internet tool out there. Maybe you've heard of it. It's called
"Google" and it does a wonderful job finding things on the Internet for
you. No doubt you'll have some rationale for discounting every negative
comment found on the Internet related to "const" in C++, but the
comments are at least out there for you to discount.

Pete
 
Z

Zach

Actually, yes you are.

You specifically claim that "const" is something "C++ gets hand down
correct".  The implication is that C# doesn't.  If saying that C# is
incorrect and C++ is correct isn't a clear statement that C++ is
superior to C#, I don't know what would be.

Figures, since you can't seem to back up anything else you're saying,
it's no surprise that you "don't know what would be". Yes, the
implication is that C# is incorrect -on one specific point-. By your
logic, if A does *anything* better than B, then A is superior to B.
What happens if B also does something superior to A? Are they now
both completely superior to each other? How does that work?

By denying that this is possible, you are claiming C# is absolutely
perfect. Is this now your position? Puhlease. All languages have
flaws, including C++, including C#. C++ might even have more flaws
than C#. OMG I SAID IT. But simply responding with a "talk to the
hand" as soon as soon as someone presents detailed rationale is a
pretty quick path to discrediting yourself.

Ironically, the only person here who seems to use both languages
regularly and enjoy both languages and have a completely objective
(not to mention informed) view of each language's pros and cons is
myself.
The rest of your post reads like the usual religious-war stuff: you
presuppose the superiority, and then use that supposition as "proof"
that someone with a counter-argument must just not understand the
superior feature.

Are you kidding me? I gave detailed explanations of how this
particular feature completely transcends ANY PROGRAMMING LANGUAGE, so
what exactly am I being religious about? Certainly not C++, since
that isn't even what this is about. Here's a hint: The programming
lanuage D gets it even better than C++. And yet, it's neither
superior nor inferior to C++, just as C++ is neither inferior nor
superior to C#. Do you see how this works yet?

That you don't understand constness in C++ is not a supposition, it is
actually more like a hypothesis. Hypothesis, if you care to look up
the definition, is an "educated guess". Educated because all your
counter arguments about it demonstrate that if you actually had used
it, and if your retelling of your experiences using it were in fact
truthful, then you were doing it wrong. That part is a fact.

[Fact] IF you were telling the truth about your experiences, THEN
you were doing it wrong.
[Hypothesis] You don't completely understand the use of the 'const'
keyword in C++.

Whatever.  Fact is, you aren't going to get this in C#.  

Surely if you have such authority on the design and future of C# you
should be able to present a rational argument about the cons of this
idea I've discussed.
As for the discussion on the topic by others, there's this great
Internet tool out there.  Maybe you've heard of it.  It's called
"Google" and it does a wonderful job finding things on the Internet for
you.  No doubt you'll have some rationale for discounting every negative
comment found on the Internet related to "const" in C++, but the
comments are at least out there for you to discount.

It's ok, I understand. As soon as I said "C++" you assumed that I had
some alterior motive to come and troll about how C# is a terrible
language, and in your haste you ended up being the only one spouting
off snide remarks not backed by any sort of facts or reason.

Let me ask this: Do you know *anything at all* about programming
language theory, which is the only way you can realistically have
anything useful to say about my original post? Or are you just a code
monkey?

[Hypothesis] The latter. It would take less than 2 seconds for
anyone in the former category to realize that C++'s const keyword is
just one implementation of a much more general programming language
concept.

Don't take criticism of your "baby" so personally.

“Criticism may not be agreeable, but it is necessary. It fulfils the
same function as pain in the human body. It calls attention to an
unhealthy state of things.” --Winston Churchill.
 
J

JT

For what it's worth, I've been programming for 27+ years, mostly in C and
C++ (3-4 years of C# now), and I strongly agree with you. Both languages
have their pros and cons but C# would be much better with "const" than
without it for the usual reasons. These reasons are self-evident in spite of
Peter's denials but he often clings to misguided beliefs that just don't
stand up to reason. I wouldn't waste my time arguing with him.
 
Ad

Advertisements

P

Peter Duniho

Zach said:
[...] Yes, the
implication is that C# is incorrect -on one specific point-.

Apology accepted.
By your
logic, if A does *anything* better than B, then A is superior to B.

I never suggested any such thing. Did you bother to read what I wrote?
Specifically, from my original reply, which you quoted: "You are at the
very least making that statement with respect to a specific feature".
The very statement to which you took such offense made exactly the
specific assertion (and no broader) you now acknowledge you were in fact
making.
[...]
Ironically, the only person here who seems to use both languages
regularly and enjoy both languages and have a completely objective
(not to mention informed) view of each language's pros and cons is
myself.

You are wrong on all points:

-- You are not the only person here who uses both languages regularly
-- You are not the only person here who enjoys both languages
-- You most certainly do not have "a completely objective view";
your rant is proof-positive of that.

In fact, your arrogant attitude that your view is 100% correct, that no
one else could possibly have any justifiable disagreement with your
view, and that anyone who does disagree should be subjected to your own
insults and dismissiveness is an entertaining ironic example of exactly
how you _don't_ have "a completely objective" view.

You've already committed your point of view to your dogma. You have no
room to accept differing opinions. This is the exact opposite of
"objective".
[...]
Surely if you have such authority on the design and future of C# you
should be able to present a rational argument about the cons of this
idea I've discussed.

You didn't "discuss" the idea. You dropped it like a bomb, making it
clear from the outset you believe it dogmatically. You even explicitly
pointed out that you can't actually _explain_ why it's a good idea ("I
can't even begin to explain how useful this is"). Just that you think
it is.

It's clear enough from your original post and your reaction that you are
not interested in "a rational _discussion_" about the issue, and frankly
there's really no interest on my part for an argument per se.

In any case, as far as me being an authority: I don't have the authority
to state unequivocally that you'll never see "const" in C# the way you
want it. There's always the possibility I'm wrong. But, I doubt I am;
I've seen enough commentary from the language designers and other
insiders to know it's not even going to be a welcome feature, never mind
one likely to make past the bar for being included.

Frankly, you aren't even the first person to post here saying they want
"const" methods in C# (even if you are the most vehemently dogmatic
about it). And you certainly aren't the first person to think that
"const" somehow creates some huge advantage in code, when in fact it
doesn't (the class of bugs "const" would prevent are just not a
significant problem, and there are too many ways around "const" anyway).
But that doesn't mean you're right.

Pete
 
J

JeffWhitledge

Has anyone ever seen any rationale for why the language designers
opted not to add 'const' qualifiers?

I seem to remember reading just such a rational a couple of years ago,
but, sadly, I cannot remember anything about it. I do think they
considered including it at one time, though.

More to the point, version 4 of the .Net Framework is going to include
"code contracts," which may address some of the reasons for having
"const". In particular, the contract framework includes an OldValue<T>
memeber that may be used to verify that particular values are
unmodified by a method. Yes, this is far less of an assurance than
"const" would be, but it is something. And the totallity of the
contracts system has the potential for going very far in ensuring
program correctness.

I tend to put a lot of assertions in my code already, and they have
proven useful many times. I can't wait to start using code contracts
in the future.

Also, C#, starting in version 3, has added a lot of functional
language features. Immutability of data structures is a key component
of the functional language concept, so it wouldn't surprise me at all
to see even more language support for it in the future.
 
P

Peter Duniho

Zach said:
this is a rant. I want constness in C# the same way it is implemented
in C++. I'm not here to argue that C++ is superior to C# or C# sucks
or anything like that. They're both awesome languages when used for
the problem domains they excel at.

One thing C++ gets hands down correct though is constness.

Re-reading this message thread, I believe I may have overreacted to the
above. I apologize for that.

That said, it is still my opinion that you are overstating the benefit
and understating the difficulty of implementing "const" in C#.

As far as specific statements in the OP are concerned:
[...] It is
immensely frustrating that with the current state of the language,
under no circumstances do I ever have any kind of guarantee about the
state of an object after invoking a function which takes an instance
of that object as an argument.

I'll more gently reiterate my previous point: C++'s "const" doesn't give
you that kind of guarantee, and if you do want that kind of guarantee it
is simple enough to encapsulate it in your code in other ways.
Take a collection for example. Collections should never need to
modify the state of the underlying object if you're simply asking for
the length. [...] In any case, why can't the Length()
function let the caller know as part of its signature that it plays
nice? Then, if I implement some serializer that serializes lists by
taking a reference to the list as an argument, that function can also
document that it plays nicely on lists by specifying the argument
const.

Unfortunately, the above presupposes the benefit of "const". You
describe the behavior you want, but not why it would be such an
improvement to the code to justify a new language feature for it, never
mind why C++'s "const" would be the right manifestation of that feature.
For anyone who's never used C++, I can't even begin to explain how
useful this is. But take my word that it results in better code. Not
better code than C#, just better code than it would if const didn't
exist.

Again, this is not an argument in favor of "const". "Take my word"
doesn't suffice. You need to be able to "explain how useful this is",
and you need to be able to do it for people who have never used C++.

After all, where would C++ be if no one could explain the benefit of
"const" prior to the point where it was included in the language?
Has anyone ever seen any rationale for why the language designers
opted not to add 'const' qualifiers?

See my reply to Jeff, where I include various links found using Google.

I will overlook all of your ad hominem attacks on me; they are
unfounded, unproductive, and most likely a direct consequence of my
initial overreaction (i.e. my fault). If you want to proceed with a
_productive discussion_ on the topic, in which you can refrain from
accusing me or others of simply being poor programmers just because we
don't see things your way, I welcome the opportunity to try again
without all the hostility.

Pete
 
P

Peter Duniho

JeffWhitledge said:
I seem to remember reading just such a rational a couple of years ago,
but, sadly, I cannot remember anything about it. I do think they
considered including it at one time, though.

Since I know how to use Google, I went ahead and did some browsing.
Here are three links that provide at least some insight into the design
process:

http://blogs.msdn.com/ericgu/archive/2004/04/22/118238.aspx
http://blogs.msdn.com/slippman/archive/2004/01/22/61712.aspx
http://www.artima.com/intv/choicesP.html

The last link is an interview with Anders Hejlsberg (arguably the
"father of C#"). Near the end he comments briefly on the question.

I also found this link, which includes a speculative answer from Jon Skeet:
http://stackoverflow.com/questions/528122/why-doesnt-c-offer-constness-akin-to-c
More to the point, version 4 of the .Net Framework is going to include
"code contracts," which may address some of the reasons for having
"const". In particular, the contract framework includes an OldValue<T>
memeber that may be used to verify that particular values are
unmodified by a method. Yes, this is far less of an assurance than
"const" would be, but it is something. And the totallity of the
contracts system has the potential for going very far in ensuring
program correctness. [...]

Actually, the contract feature provides stronger assurance than "const"
would. In C++, "const" doesn't ever give you any sort of real
guarantee. It's non-transitive (so observable mutations can occur in
"correct" code), and it's not enforced at run-time (so incorrect code
can break the contract, and without any real difficulty either).

The quote from Hejlsberg may seem a bit glib, but I feel he sums up the
issue quite nicely. You can see more of the detail in the other
articles; the basic problem is that for "const" to be really useful and
practical, you have to be able to get rid of it so that you can deal
with code that doesn't support it (either because it won't, or in many
cases because it can't). But for "const" to be really useful and
practical, you _can't_ be able to get rid of it, because otherwise it's
not providing any real guarantees that can be used in terms of proving
code correctness.

This contradiction significantly limits its utility, and especially in
the managed context where run-time guarantees are paramount. All of
C#'s compile-time mandates are mirrored in the run-time. They aren't
there just to ease development (though that's certainly one effect);
they provide genuine, run-time guarantees.

Pete
 
J

JeffWhitledge

JeffWhitledge said:
In particular, the contract framework includes an OldValue<T>
memeber that may be used to verify that particular values are
unmodified by a method. Yes, this is far less of an assurance than
"const" would be, but it is something. And the totallity of the
contracts system has the potential for going very far in ensuring
program correctness. [...]

Actually, the contract feature provides stronger assurance than "const"
would.  In C++, "const" doesn't ever give you any sort of real
guarantee.  It's non-transitive (so observable mutations can occur in
"correct" code), and it's not enforced at run-time (so incorrect code
can break the contract, and without any real difficulty either).

I have never used the const feature of C++, but the example given in
the OP indicates a compile-time check on attempts to write to the
members of a const object. In the absense of any casting-away, this
appears to be a fairly strong assurance.

The contracts solution using OldValue<T> (which I have also not yet
used) looks rather weak by comparison. It merely provides a shallow-
copy of the original object. This implies that additional work will be
necessary to check that no changes have been made, and, in particular,
reference-type property values will need extra attention (and
properties of the properties, etc.). Further, the checks are not made
at compile-time, but violations must be checked at run time, which
requires thorough test-case coverage to locate contract violations.
Further, there is no automatic or systematic mechanism for
communicating to the method's users the intent of the method to not
mutate its parameters, either by method definition (such as "ref" and
"out") or by documentation (such as "///<exception>...).

Using the current technologies, it looks like a wash to me, between
the two solutions.

The beautiful thing about code contracts, in my opinion, is the
possibilities of what may be done with them in the future. They will
enable static checks of the code using theorem provers, which really
will be able to make guaruntees about the correctness of code at pre-
compile-time. That's a pretty exciting prospect! (Exciting to people
who are obsessed with correctness and reliability above all other
things, of course, but, really, who isn't like that?)
 
Ad

Advertisements

P

Peter Duniho

JeffWhitledge said:
I have never used the const feature of C++, but the example given in
the OP indicates a compile-time check on attempts to write to the
members of a const object. In the absense of any casting-away, this
appears to be a fairly strong assurance.

"In the absence of any casting-away" makes any further analysis
uninformative. That's a fundamental problem with C++'s "const". It
provides no real guarantees. It works only when _all_ of the code
involved is in 100% compliance. This has a variety of negative
implications, including the difficulty in retro-fitting and the complete
inability to interface with external code.

If one is willing to bear those constraints, you get the benefit of
"const". But if not, then you can't actually rely on the places in the
code where "const" is used.
The contracts solution using OldValue<T> (which I have also not yet
used) looks rather weak by comparison. It merely provides a shallow-
copy of the original object.

I didn't intend to imply that "OldValue<T>" is necessarily _the_
replacement for C++'s "const". My point is, rather, that code contracts
more generally provide for a much more robust and varied way to enforce
specific invariants that are supposed to apply to the code. And as you
even note, code contracts in .NET are in their infancy and can (and
will) be extended to provide even more functionality (including _real_
compile-time assurances).

One of the biggest advantages C++'s "const" has is its conciseness. But
that conciseness comes at a cost, a significant one with respect to the
utility of whatever assurance it offers. It's just not a very strong
assurance.
This implies that additional work will be
necessary to check that no changes have been made, and, in particular,
reference-type property values will need extra attention (and
properties of the properties, etc.). Further, the checks are not made
at compile-time, but violations must be checked at run time, which
requires thorough test-case coverage to locate contract violations.

All true. But, the fact that violations "must be checked at run time"
is an _advantage_. It means that you can interface with external code,
without having to rely on that external code supporting the exact same
"const"-label the contracted code is using.

Compile-time checks are great when feasible, but this isn't a case where
it's feasible. You can't actually do anything critical that would rely
on C++'s "const" because it's too easy to violate that label.
Further, there is no automatic or systematic mechanism for
communicating to the method's users the intent of the method to not
mutate its parameters, either by method definition (such as "ref" and
"out") or by documentation (such as "///<exception>...). [...]

I find documentation to be a very useful and practical solution for
_communication_.

Pete
 
J

JeffWhitledge

I didn't intend to imply that "OldValue<T>" is necessarily _the_
replacement for C++'s "const".  My point is, rather, that code contracts
more generally provide for a much more robust and varied way to enforce
specific invariants that are supposed to apply to the code.  And as you
even note, code contracts in .NET are in their infancy and can (and
will) be extended to provide even more functionality (including _real_
compile-time assurances).
Agreed.

All true.  But, the fact that violations "must be checked at run time"
is an _advantage_.  It means that you can interface with external code,
without having to rely on that external code supporting the exact same
"const"-label the contracted code is using.

Had const been included from the start as part of the CLR code-safety
verification, then the problems you note might have been avoided to a
degree. But, yeah, there's no going back now.
Further, there is no automatic or systematic mechanism for
communicating to the method's users the intent of the method to not
mutate its parameters, either by method definition (such as "ref" and
"out") or by documentation (such as "///<exception>...).  [...]

I find documentation to be a very useful and practical solution for
_communication_.

Indeed, my complaint is that there is not yet any required,
systematic, in-your-face discoverable mechanism for communicating this
information (such as exists for a few other things). The mutability/
immutability of method parameters must be inferred from the
documentation text. This is certainly workable, and additional
required elements might be unnecessarily burdensome, but I think the
case can be made that such things would be worthwhile. Perhaps some
representation of the method contracts will find their way into the
IDE tooltip system at some point. That would be pretty sweet. If not,
then I might even write such a thing myself.
 
Z

Zach

"In the absence of any casting-away" makes any further analysis
uninformative.  That's a fundamental problem with C++'s "const".  It
provides no real guarantees.  It works only when _all_ of the code
involved is in 100% compliance.  This has a variety of negative
implications, including the difficulty in retro-fitting and the complete
inability to interface with external code.

If one is willing to bear those constraints, you get the benefit of
"const".  But if not, then you can't actually rely on the places in the
code where "const" is used.

As with C#, this is a case of where things would have been better if
it had been done that way from the start, and now there's no going
back. For example, modern C++ provides a const_cast<> operator that
is used to cast away const. Unfortunately, you can still used old
style casts to cast away const.

const Foo* foo = new Foo();
Foo* foo2 = (Foo*)foo; //Old-style cast, unsafe and
unfortunate

const Foo* foo - new Foo();
Foo* foo2 = const_cast<Foo*>(foo); //New-style cast, much better.

While it still ultimately breaks the contract, at least the situation
can easily be detected either during code review, or even by static
analysis tools by simply grepping your source tree.

The ability to cast away const is one of the reasons I said earlier
that D got it even better than C++. Of course that's no surprise,
since it was designed specifically to solve some of the problems that
plague C++. Technically, in D you can still cast away the code
contracts, but according to the language standard it leads to
undefined behavior, so the compiler can detect it and give a warning
or an error.


I didn't intend to imply that "OldValue<T>" is necessarily _the_
replacement for C++'s "const".  My point is, rather, that code contracts
more generally provide for a much more robust and varied way to enforce
specific invariants that are supposed to apply to the code.  And as you
even note, code contracts in .NET are in their infancy and can (and
will) be extended to provide even more functionality (including _real_
compile-time assurances).

Indeed, const (as a programming concept, not as a C++ keyword) is only
a small subset of what is achievable with real code contracts.

One of the biggest advantages C++'s "const" has is its conciseness.  But
that conciseness comes at a cost, a significant one with respect to the
utility of whatever assurance it offers.  It's just not a very strong
assurance.


All true.  But, the fact that violations "must be checked at run time"
is an _advantage_.  It means that you can interface with external code,
without having to rely on that external code supporting the exact same
"const"-label the contracted code is using.

It depends. Performance is a concern sometimes, even when using C#.
Everyone is always quick to tell people that if performance is their
concern they should be using a different language, but take Xna for
example. It *does* make a difference if you're doing additional
runtime checks in a game's update loop running 100 times per second.
Runtime checking is of course good, but it's not the end-all
solution. Compile time checking not only increases code correctness /
security, but also is an aid for rapid application development. Who
wants to run a test suite just to verify that their code contracts are
being met, when it could just not compile in the first place? Each
type of checking is important in certain scenarios.

Compile-time checks are great when feasible, but this isn't a case where
it's feasible.  You can't actually do anything critical that would rely
on C++'s "const" because it's too easy to violate that label.
I should point out that sometimes it's actually necessary to violate
the label. Suppose, for example, that you want to adapt an interface
to count how many times each method has been called. you have this
interface IInterface, so you simply implement it, add a member
variable for the count, and each time a method is called, increment
the count. If any method in the interface were const, or had some
code contract stating that it did not modify the state of the class,
it would fail regardless of whether the code contracts were checked at
compile time or runtime. There's not a good solution to this problem,
even with code contracts. So C++ provides the mutable keyword, which
again you can easily grep for, similary to const_cast. Yes, it limits
the guarantees and the amount of work a static analysis tool can use,
but at the very least a static analysis tool can you tell you exactly
where code contracts are violated.

Further, there is no automatic or systematic mechanism for
communicating to the method's users the intent of the method to not
mutate its parameters, either by method definition (such as "ref" and
"out") or by documentation (such as "///<exception>...).  [...]

I find documentation to be a very useful and practical solution for
_communication_.

It's useful, but people overdo documentation. I know it's not popular
to say, but it's true. That's why C# distinguishes between ref and
out parameters. Technically there's no difference, but by making a
distinction the compiler is your documentation, leading to more
concise code.

Really, there's nothing I hate more than seeing a class where 20% or
more of the source file is comments, it shouldn't be that difficult to
write clear and concise code.
 
H

Harlan Messinger

Zach said:
Because I don't want the object to *always* be immutable. Being able
for object X to assert that it must never be mutated is only half the
battle.. The other half is allowing function Y to inform the *caller*
that X *will not* mutated. That is the whole point.

Aha. So, you don't want the object always to be immutable. In that case,
if you don't trust a method that has no reason to change your object not
to change your object, then how do you trust ANY method not to do
something it isn't supposed to do? If you've got a list of some kind,
for example, and you trust Add and Remove to behave properly while they
do their jobs, without worrying that they're secretly or inadvertently
wreaking havoc on your objects, then it's inconsistent to fret that
Count might not be equally well behaved.
 
J

J.B. Moreno

Zach said:
Because I don't want the object to *always* be immutable. Being able
for object X to assert that it must never be mutated is only half the
battle.. The other half is allowing function Y to inform the *caller*
that X *will not* mutated. That is the whole point.

The problem is, and the reason why immutable is better, is that is the
wrong end of the equation.

You don't want the procedure to "promise" the caller that it won't make
any changes, you want the ability to allow the caller to PREVENT the
procedure from making changes...

Given that consts doesn't create an immutable object, the promise isn't
worth the paper it's written on.

What it does do is prevent the equivalent of typo's, so it's not
useless, but it's not tremendously useful either.
 
Ad

Advertisements

Z

Zach

The problem is, and the reason why immutable is better, is that is the
wrong end of the equation.

You don't want the procedure to "promise" the caller that it won't make
any changes, you want the ability to allow the caller to PREVENT the
procedure from making changes...

Given that consts doesn't create an immutable object, the promise isn't
worth the paper it's written on.

What it does do is prevent the equivalent of typo's, so it's not
useless, but it's not tremendously useful either.

It depends. The only way to really preevnt is through runtime
checking. Of course this is sometimes useful, and I don't advocate a
strictly compile-time solution, any ideal solution would have a
mixture of both. Although in some cases the performance overhead of
runtime checking is not worth the tradeoff. I know this is not a
*huge* use case for C#, but it is a use case, especially with
Microsoft's push for game development in Xna.

Also, as mentioned in a previous post, immutable objects are nice, but
what const really gives you is the ability to control the granularity
of the immutability. Is it only a single field in an object, is the
method operating on the object, is it this particular instance of an
object but not other instances, etc. C# and C++ are too different to
provide a direct mapping of the concept, but at least some compile
time aspect of granular constness would be nice, even if it's not
identical to the way C++ has done it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top