Readonly locals?

W

Weeble

I was surprised to discover today that local variables can't be
"readonly". (They can be "const", but that's only for compile-time
constants, not something that might be calculated at run-time.) I
would have expected such a variable to allow assignment via an
initialiser, but to be readonly for the remainder of the method, i.e.
it would be an error to place it on the left of an assignment or to
use it as an out parameter. This would be useful to let others
maintaining the code know that the value/reference assigned to the
variable at the top of the method won't have changed further down the
method, especially so when the objects involved are immutable. I can
only assume that it's not allowed simply because the feature is not in
high demand? (Certainly, it's nowhere near as important as being able
to have readonly fields, simply because there are so many more places
to search for code that might modify a field.)

I searched this newsgroup for any mention of readonly local variables,
but the only mention was from years ago. Does this mean that nobody
would find such a feature useful? Am I missing some way to get a
similar effect?
 
B

Bob Powell [MVP]

You can simulate something like what you want with a property as shown
below.

int _p;
bool _pset;
int P
{
get{return _p;}
set
{
if(!_pset)
{
_pset=true;
_p=value;
}
}
}

To expect this of the compiler for a field is, IMO, a nonsense.

A class should have access to its fields but allowing public access to
fields breaks the rules of encapsulation so classes must provide properties.

A class should have enough knowledge of it's own internal workings to not
break rules that it sets for itself. This implies that the need for such a
construct as an immutable or "set-once" local variable is superflouous.





--
--
Bob Powell [MVP]
Visual C#, System.Drawing

Ramuseco Limited .NET consulting
http://www.ramuseco.com

Find great Windows Forms articles in Windows Forms Tips and Tricks
http://www.bobpowell.net/tipstricks.htm

Answer those GDI+ questions with the GDI+ FAQ
http://www.bobpowell.net/faqmain.htm

All new articles provide code in C# and VB.NET.
Subscribe to the RSS feeds provided and never miss a new article.
 
J

Jon Skeet [C# MVP]

Bob Powell said:
You can simulate something like what you want with a property as shown
below.

That wouldn't work recursively though, because it wouldn't be in the
stack frame of the method.
To expect this of the compiler for a field is, IMO, a nonsense.

A class should have access to its fields but allowing public access to
fields breaks the rules of encapsulation so classes must provide properties.

I didn't see anything in Weeble's post which talked about public
fields. Which bit of the post are you responding to?
A class should have enough knowledge of it's own internal workings to not
break rules that it sets for itself. This implies that the need for such a
construct as an immutable or "set-once" local variable is superflouous.

There are many things which are superfluous, but still helpful. The
"using" statement is superfluous in the face of try/finally - but when
I'm writing Java I miss it terribly.

I for one would welcome the ability to use the readonly modifier for
local variables. I don't think I'd use it terribly often (I don't in
Java where it's available) but occasionally it could be useful, and I
don't think it would add any significant complexity to the language.
 
J

Jeroen Mostert

Bob said:
You can simulate something like what you want with a property as shown
below.

int _p;
bool _pset;
int P
{
get{return _p;}
set
{
if(!_pset)
{
_pset=true;
_p=value;
}
}
}

To expect this of the compiler for a field is, IMO, a nonsense.
Well, as far as I can tell your approach is "a nonsense". What advantage do
you foresee from having a write-once property?

The critical advantage from a read-only field comes from knowing that its
value will be determined at construction time, and not changed afterwards. So:

private readonly int p;
public int P { get { return p; } }

Reasoning about P is now trivial; it will never change. You're free to cache
it, share it, or provide alternate representations, without having to worry
about keeping anything in sync. Threading issues disappear if you hand off
copies, which you can safely do since you'll never have out-of-date copies.
In short: immutability is a useful thing.

A write-once property is much less useful, because the implementer of the
class still doesn't know exactly when the property will be written to, so
the (limited) immutability is something you can hardly count on. That's not
even taking into account that such a property is quite unintuitive to
clients (whether internal or external).
A class should have access to its fields but allowing public access to
fields breaks the rules of encapsulation so classes must provide
properties.
I'm not sure you understood the OP's meaning. He was talking about local
*variables*, i.e.:

private int interestingMethod(int a, int b, int c) {
readonly int d = a * 24 + b / 3 + c; // Does not compile
...
// If it did, we could forget about some potential issues by knowing
that d will never change
}

You can do this in Java with "final". You can't do it in C#. It would have
been easy enough to add, but it just wasn't. It's one of those things.

What use is an immutable local variable, you ask? Well, what use is a
*mutable* local variable? You'll often declare temporary variables that hold
the value of some involved expression you don't want to retype (or one that
really should be evaluated only once), but which are never changed
afterwards. Reusing such a variable and assigning a different value is
either a serious mistake or something that will make the code a whole lot
harder to read (because after point X, your temporary variable suddenly
means something different). If you could declare it readonly, you couldn't
fall into this trap in the first place.

Immutable locals are also of use in refactoring. Transforming the code to a
new form (preferrably one with smaller independent parts) by introducing or
eliminating local variables is a lot safer if you can guarantee that a
variable isn't assigned to halfway down the method, or modified by passing
it as a ref parameter somewhere. Automated refactoring tools can help here,
but if you don't have them (or they can't do what you want)
compiler-enforced immutability can be quite useful.
A class should have enough knowledge of it's own internal workings to
not break rules that it sets for itself.

But a class doesn't set rules or break them, the programmer does. This is
the same as saying "the programmer should be infallible". The programmer
should certainly be free to make their own life easier by preventing
themselves from making mistakes in the first place.
This implies that the need for such a construct as an immutable or
"set-once" local variable is superflouous.
Functional programming languages would disagree, as would the designers of
LINQ. You are correct inasmuch as a language is not made any richer by
providing a way for marking things immutable, but it is made more
expressive, and this can benefit both programmer and compiler.
 
M

Marc Gravell

Well, as far as I can tell your approach is "a nonsense". What advantage do
you foresee from having a write-once property?

That is actually a big issue in the parallel extensions framework,
with WriteOnce<T> being an important type in the CDS library...

I'm just saying...

Marc
 
J

Jeroen Mostert

Marc said:
That is actually a big issue in the parallel extensions framework,
with WriteOnce<T> being an important type in the CDS library...

I'm just saying...
Well, it *does* provide some form of immutability... But a kind that's not
easy to use in most scenarios. Multithreading really benefits from
immutability, so in that sense it's no surprise that PFX would take it in
any way, shape and form, but you usually wouldn't be able to capitalize on
it much.
 
M

Marc Gravell

I agree that it isn't really useful in this scenario, but I have got a
few thoughts about when a WriteOnce<T> might be useful. In fact, we used
something very similar in "Push LINQ" (Jon's MiscUtil), which is devoid
of threading. And I can perhaps see a potential (if slightly clumsy) use
in giving immutable* classes object-initializer capability. Perhaps
premature, though ;-p

Marc

*=well, quasi-immutable
 
J

Jon Skeet [C# MVP]

I agree that it isn't really useful in this scenario, but I have got a
few thoughts about when a WriteOnce<T> might be useful. In fact, we used
something very similar in "Push LINQ" (Jon's MiscUtil), which is devoid
of threading. And I can perhaps see a potential (if slightly clumsy) use
in giving immutable* classes object-initializer capability. Perhaps
premature, though ;-p

*=well, quasi-immutable

I'd prefer fully immutable, via an automatic builder pattern. When the
classes are properly immutable, with readonly fields, the JIT can
understand that and optimise accordingly.

I blogged about this a while ago, in a "not fully thought through but
hopefully giving ideas to smarter people" kind of way:
http://msmvps.com/blogs/jon_skeet/archive/2008/03/16/c-4-immutable-type-initialization.aspx

(Marc has already seen this as he contributed comments - I thought
others might be interested.)

Jon
 
W

Weeble

Jeroen said:
I'm not sure you understood the OP's meaning. He was talking about local
*variables*
[...]
You can do this in Java with "final". You can't do it in C#. It would have
been easy enough to add, but it just wasn't. It's one of those things.

Yes, that's exactly what I meant. I can live without it, but it seems
like it would be nice to have, especially when writing in a functional
style, and it doesn't seem like it would be much of a burden on the
compiler. I'm not entirely sure what Bob Powell thought I meant.
 

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