Bob Powell [MVP] wrote:
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.
--
J.