Is const allowed anywhere?

N

neelsmail

Hi,

I have just started learning C# ; I was working in C++ till now (and
would like to if allowed, but learning new things dont hurt). I am
used to specifiying "const" to get the assurance that unless someone
specifically cast-away the constness, object wont change. So, as part
of my first ever program I wrote a following class -

public class FirstOne {
public int intTry;
public FirstOne() {
intTry = 0;
}

//public FirstOne(readonly FirstOne o)
//public FirstOne(const FirstOne o)
public FirstOne(FirstOne o) {
intTry = o.intTry;
o.intTry = -100; // This would be possible if I can't make
the parameter const..

}
}

Since class in C# is reference type (still getting hang of the
concept) object 'o' is already a reference, I am just trying to make
it const so that it doesn't change. But the syntax (commented lines)
does not work. Is it even possible to have const ref or it's just a
glitch in my C# syntax understanding?

Thanks in advance,
Neel.
 
M

Marc Gravell

No is the short answer; if a class is mutable (which yours is), then
any caller can update properties (or fields if they have access).

You could perhaps make the class immutable, but this prevents anybody
from changing the contents (you need to recreate the object from
scratch to "change" it). You could create an interface with only the
"get" accessors, but that doesn't prevent you from casting back to the
real type.

Otherwise you could perhaps pass clones around, but that is an
overhead and relies on the various parties playing ball. There is no
C# syntax to do what you want (treat a mutable object as immutable
within a scope).

Marc
 
M

Marc Gravell

Just in case I missed your meaning; you can do the following

public readonly int intTry;

now *only* the constructor can set intTry.

Also - can I recommend using properties instead of direct fields? In
simple cases this will be inlined by the JIT anyway, but gives you a
lot more flexibility to add functionality; as an example (with a
use-case)...

private void CheckEditable() {
// allow some kind of lock/unlock mechanism...
if(!IsEditable) throw new InvalidOperationException("The record is
not currently editable");
}
private int shoeSize;
public int ShoeSize {
get {return shoeSize;}
set {
if(value==ShoeSize) return; // no change
if(value < 0 || value > 20) throw new
ArgumentOutOfRangeException("something");
CheckEditable();
shoeSize= value;
OnPropertyValueChanged("Age"); // "observer" notification
}
}
 
N

neelsmail

Thanks Marc.
now *only* the constructor can set intTry.

This is not my intention. I just want to have option of sending object
of this class as read-only/const object to methods/constructors when
required. I believe what you said in your earlier post , "No is the
short answer", is the short but correct answer :)

Even if I have just started learning it now, I can't help but wonder
why it was left out..
Also - can I recommend using properties instead of direct fields?

Yes, what you said about using properties instead of fields makes much
more sense.

Thanks,
Neel.
 
J

Jon Skeet [C# MVP]

Even if I have just started learning it now, I can't help but wonder
why it was left out..

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

<quote>

Anders Hejlsberg: Yes. With respect to const, it's interesting, because
we hear that complaint all the time too: "Why don't you have const?"
Implicit in the question is, "Why don't you have const that is enforced
by the runtime?" That's really what people are asking, although they
don't come out and say it that way.

The reason that const works in C++ is because you can cast it away. If
you couldn't cast it away, then your world would suck. If you declare a
method that takes a const Bla, you could pass it a non-const Bla. But
if it's the other way around you can't. If you declare a method that
takes a non-const Bla, you can't pass it a const Bla. So now you're
stuck. So you gradually need a const version of everything that isn't
const, and you end up with a shadow world. In C++ you get away with it,
because as with anything in C++ it is purely optional whether you want
this check or not. You can just whack the constness away if you don't
like it.

</quote>
 
B

Ben Voigt [C++ MVP]

Jon Skeet said:
From http://www.artima.com/intv/choicesP.html

<quote>

Anders Hejlsberg: Yes. With respect to const, it's interesting, because
we hear that complaint all the time too: "Why don't you have const?"
Implicit in the question is, "Why don't you have const that is enforced
by the runtime?" That's really what people are asking, although they
don't come out and say it that way.

The reason that const works in C++ is because you can cast it away. If
you couldn't cast it away, then your world would suck. If you declare a
method that takes a const Bla, you could pass it a non-const Bla. But
if it's the other way around you can't. If you declare a method that
takes a non-const Bla, you can't pass it a const Bla. So now you're
stuck. So you gradually need a const version of everything that isn't
const, and you end up with a shadow world. In C++ you get away with it,
because as with anything in C++ it is purely optional whether you want
this check or not. You can just whack the constness away if you don't
like it.

</quote>

And he is totally wrong. He appeals to the refactoring a library written
with const -- designing for const-correctness carries none of his presumed
drawbacks. I never use const_cast<> in my programs, nor a C-style cast to
do the same... if a third-party library doesn't accept a const pointer when
I think it should, I assume it is reserving the right to overwrite that
buffer, and I need to make a copy for it to act on. That option is always
available, would be even easier in .NET with the Clone() method, and is
safe.
 
N

neelsmail

I do firmly believe that I should have a way to be sure that the
object that I am sending in will not change under normal circumstances
and should be able to assure the user of my class that if I am the
class writer. I would have imagined that instead of not allowing
"const", it would not provide casting (in any form) if the object is
const.

I am similarly confused by the fact that (taking example I have
mentioned), only user defined reference type const variable I can
create is -
const FirstOne = null;

since I am not sure what am I supposed to do with it. But then, that
can be gap in my understanding as far as use of it is concerned.

Thanks,
Neel.
 
M

Marc Gravell

Re the "const reference type" variable... the main thing here is that
const expressions are evaluated at compile-time (not run-time), and
hence they can't really do much with objects - just literals. Strings
are treated a little sneakier.

In the case you are talking about, a readonly static field might be in
order, perhaps initialised in a static ctor if the initialisation is
non-trivial (or inline with the field declaration if it is simple).
But note that this *still* doesn't stop you from changing properties
of the object - it only stops you from changing the reference itself.
Hence the object would ideally be immutable in this case.

Some classes exhibit a "make a readonly copy / make me readonly"
behavior for this, but it itsn't common.

i.e.

class SomeClass {

static readonly someStaticField
static SomeClass() { // static ctor
someStaticField = SomeWayOfCreatingTheStaticInstance();
}
public SomeClass() {}// instance ctor

void SomeMethod() {
// make use of someStaticField
}

}

Marc
 
N

neelsmail

Thanks Marc.

I read about the approach you are referring to, but, again, all I want
to do is make a new object I am about to create a constant object. I
may be wrong but if I consider making object read-only even that has
to be a class level object which may not be needed (I tried to make
const object in local scope through read-only and C# didnt like
it :) ). I would have thought that, keyword "mutable" will be absent
so that C# doesn't become another version of C++. I think what I am
getting at is, reducing complexity of all the options and their
permutations/combinations, MAY BE, was not required to be taken this
far. For example, in C++, if a function is expecting a const objec/
reference, I only have to rely on parameters if the library/class
source code isn't present, which can become headache later because in
some case library user can simply cast away const-ness. But since C#
does not allow const ref to be passed at all, all I can do is make a
clone and it may (most probably even) turn out to be expensive. But
that's just what I think... :)

Thanks,
Neel.
 

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