?? Basic C# Language Questions ??

R

Robin Bowning

Hi all,

I have two questions I was hoping someone could answer regarding C#.

First, I noticed C# does not allow local readonly variables. For example,
the following is illegal:

void X() {
readonly int i = 1;
}

I know that for this simple example I could have used const but there are
times when you must use readonly. Why can't readonly variables be local?

My second question has to do with jagged arrays. The following construct is
legal:
int[] a1 = {1, 2, 3};

but this is not:
int[][] a2 = {{1, 2, 3}, {4, 5}};

The above declaration of a2 will generate two errors (both the same):
"Array initializers can only be used in a variable or field initializer. Try
using a new expression instead."

I'm obviously missing something here. To my (obviously incorrect) way of
thinking, a2 *IS* being initialized with a variable initializer.

If I change the above declaration to this:

int[][] a2 = { new int[] {1, 2, 3}, new int[] {4, 5}};

the errors goes away. Would someone be able to clarify this behavior,
please?

Thanks very much.
 
F

Freiddie

For one thing, I don't see any reason why local variables, which are
never accessed by any external code, should be readonly. You can use
constants (equivalent of readonly). But what readonly really means is
that external code (e.g. if you're making a DLL library and someone
else is supposed to use it) cannot change this property, while you may
still be able to change the inner variable. It only applies to
properties, which are exposed to external codes.

Next, for any array the "proper" declaration is:
int[] a = new int[] { xxxxxxx ];
But C# makes it easier, by using the "less legal" version
int[] a = { xxxxxxx };
That makes it a shorthand notation.
But it doesn't apply to the inner brackets of the jagged arrays.
The notation you said to be illegal is valid for multidimensional
arrays, though.

Freiddie
http://fei.yuanbw.googlepages.com/
http://freiddy.blogspot.com/
http://scilearn.blogspot.com/
 
G

Guest

'readonly' variables can be initialized either in the declaration or in a
constructor, but nowhere else. How did you expect this to relate to local
variables?

In your array example, your first initializer is a 2-dimensional array
initializer. Your second try is appropriate for a jagged array since it is
an array of arrays.
--
David Anton
www.tangiblesoftwaresolutions.com
Instant C#: VB to C# converter
Instant VB: C# to VB converter
C++ to C# Converter: converts C++ to C#
Instant C++: converts C# or VB to C++/CLI
 
R

Robin Bowning

Below...


Freiddie said:
For one thing, I don't see any reason why local variables, which are
never accessed by any external code, should be readonly. You can use
constants (equivalent of readonly).

const is certainly not the equivalent of readonly. Sure, they're similar, to
a limited extent, but not at all the same. Try doing this:
const MyClass mc = new MyClass();

But what readonly really means is
that external code (e.g. if you're making a DLL library and someone
else is supposed to use it) cannot change this property, while you may
still be able to change the inner variable. It only applies to
properties, which are exposed to external codes.

"...what readonly really means..."? No -- you have described one possible
use of 'readonly'. What readonly means is that once a value is assigned it
cannot be re-assigned. That's all it "means". You have described one
possible intention of using 'readonly', but certainly not the only reason.
There's no sense in going into details as to *why* I want to make a local
readonly. It just seems that there's no good reason why I shouldn't be able
to.




Next, for any array the "proper" declaration is:
int[] a = new int[] { xxxxxxx ];
But C# makes it easier, by using the "less legal" version
int[] a = { xxxxxxx };

"Less legal"? There's nothing "less legal" about it.

That makes it a shorthand notation.
But it doesn't apply to the inner brackets of the jagged arrays.
The notation you said to be illegal is valid for multidimensional
arrays, though.

Yes, Thank you. I've discovered this myself. That's what I was asking about.
You basically re-phrased what I'd already stated.
 
R

Robin Bowning

David Anton said:
'readonly' variables can be initialized either in the declaration or in a
constructor, but nowhere else. How did you expect this to relate to local
variables?

Yes, I know this. But why? What's the rational? I can think of a couple good
reasons for having readonly locals but no good reasons *not* to allow them.
I already understand what is allowed/disallowed. I'm trying to get at the
rational.


In your array example, your first initializer is a 2-dimensional array
initializer. Your second try is appropriate for a jagged array since it
is
an array of arrays.

Yes, yes, yes... I know that....


--
David Anton
www.tangiblesoftwaresolutions.com
Instant C#: VB to C# converter
Instant VB: C# to VB converter
C++ to C# Converter: converts C++ to C#
Instant C++: converts C# or VB to C++/CLI


Robin Bowning said:
Hi all,

I have two questions I was hoping someone could answer regarding C#.

First, I noticed C# does not allow local readonly variables. For example,
the following is illegal:

void X() {
readonly int i = 1;
}

I know that for this simple example I could have used const but there are
times when you must use readonly. Why can't readonly variables be local?

My second question has to do with jagged arrays. The following construct
is
legal:
int[] a1 = {1, 2, 3};

but this is not:
int[][] a2 = {{1, 2, 3}, {4, 5}};

The above declaration of a2 will generate two errors (both the same):
"Array initializers can only be used in a variable or field initializer.
Try
using a new expression instead."

I'm obviously missing something here. To my (obviously incorrect) way of
thinking, a2 *IS* being initialized with a variable initializer.

If I change the above declaration to this:

int[][] a2 = { new int[] {1, 2, 3}, new int[] {4, 5}};

the errors goes away. Would someone be able to clarify this behavior,
please?

Thanks very much.
 
J

Jon Skeet [C# MVP]

There's no sense in going into details as to *why* I want to make a local
readonly. It just seems that there's no good reason why I shouldn't be able
to.

I disagree on that front. Language features need to justify themselves
for inclusion, as each one contributes (even slightly) to the
complexity of the language. For instance, would you expect to be able
to do this:

readonly int x;

if (someCondition)
{
x = 0;
}
else
{
x = 1;
}

? The compiler could guarantee exactly one assignment, but the simpler
approach would be to force assignment in the same statement as
declaration. This kind of thing would need to be addressed in the spec.
Not having the possibility at all keeps the spec simpler.

So, I think there *is* sense in saying why it would be a positive thing
to have. For what it's worth, it's available in Java, and aside from
the times where one has to use it for anonymous inner classes reasons,
I can't remember ever seeing it being used. If one keeps methods
appropriately short (e.g. easily fitting on a single page) then it
should be reasonably clear that it's not being reassigned.
 
G

Guest

I see - you want to set a variable to something at run-time (so a constant
won't work), but don't want it modifiable later in the method after assigning
a value.
--
David Anton
www.tangiblesoftwaresolutions.com
Instant C#: VB to C# converter
Instant VB: C# to VB converter
C++ to C# Converter: converts C++ to C#
Instant C++: converts C# or VB to C++/CLI


Robin Bowning said:
David Anton said:
'readonly' variables can be initialized either in the declaration or in a
constructor, but nowhere else. How did you expect this to relate to local
variables?

Yes, I know this. But why? What's the rational? I can think of a couple good
reasons for having readonly locals but no good reasons *not* to allow them.
I already understand what is allowed/disallowed. I'm trying to get at the
rational.


In your array example, your first initializer is a 2-dimensional array
initializer. Your second try is appropriate for a jagged array since it
is
an array of arrays.

Yes, yes, yes... I know that....


--
David Anton
www.tangiblesoftwaresolutions.com
Instant C#: VB to C# converter
Instant VB: C# to VB converter
C++ to C# Converter: converts C++ to C#
Instant C++: converts C# or VB to C++/CLI


Robin Bowning said:
Hi all,

I have two questions I was hoping someone could answer regarding C#.

First, I noticed C# does not allow local readonly variables. For example,
the following is illegal:

void X() {
readonly int i = 1;
}

I know that for this simple example I could have used const but there are
times when you must use readonly. Why can't readonly variables be local?

My second question has to do with jagged arrays. The following construct
is
legal:
int[] a1 = {1, 2, 3};

but this is not:
int[][] a2 = {{1, 2, 3}, {4, 5}};

The above declaration of a2 will generate two errors (both the same):
"Array initializers can only be used in a variable or field initializer.
Try
using a new expression instead."

I'm obviously missing something here. To my (obviously incorrect) way of
thinking, a2 *IS* being initialized with a variable initializer.

If I change the above declaration to this:

int[][] a2 = { new int[] {1, 2, 3}, new int[] {4, 5}};

the errors goes away. Would someone be able to clarify this behavior,
please?

Thanks very much.
 
R

Robin Bowning

Jon Skeet said:
I disagree on that front. Language features need to justify themselves
for inclusion, as each one contributes (even slightly) to the
complexity of the language. For instance, would you expect to be able
to do this:

readonly int x;

if (someCondition)
{
x = 0;
}
else
{
x = 1;
}

? The compiler could guarantee exactly one assignment, but the simpler
approach would be to force assignment in the same statement as
declaration. This kind of thing would need to be addressed in the spec.
Not having the possibility at all keeps the spec simpler.

So, I think there *is* sense in saying why it would be a positive thing
to have. For what it's worth, it's available in Java, and aside from
the times where one has to use it for anonymous inner classes reasons,
I can't remember ever seeing it being used. If one keeps methods
appropriately short (e.g. easily fitting on a single page) then it
should be reasonably clear that it's not being reassigned.


Let me offer some (admittedly subjective) justification then for why I think
it would be a positive change to have local 'readonly's.

First, they provide a useful means to communicate intent. When I'm reading
someone's code and I see 'readonly' it tells me that the author intended
this variable to be immutable. Many of us try to use "meaningful variable
names" because their use facilitates understanding of code intent.
'readonly' locals would serve the exact same purpose.

Second, it could help in code correctness. If I declare a variable as
readonly and then I later attempt to change it, I've made an incorrect
assumption somewhere and the compiler will tell me -- either I should not
have declared the variable as 'readonly' or I may be changing the wrong
variable or my understanding of the problem may not be correct.

Thirdly (and let me offer this one with a grain of salt), 'readonly' locals
may allow better IL generation. John, you're right that Java allows an
equivalent qualifier (final) on local variables. Unless I'm mistaken,
declaring a variable as 'final' in Java allowed the Java JITter (Hotspot) to
generate more efficient code.

Now, I may be completely wrong about the third point or perhaps it's a point
that does not even apply to C#/CLR. Even so, I think the first two points
are still valid and are advantages we harvest if 'readonly' locals are
allowed. Whether the advantages of 'readonly' locals outweigh the added
complexity they bring to the spec is an open question.

My main motivation for the original post was to discover whether there was
some intrinsic technical issue that precluded their existence and from the
responses so far, it seems here is not.
 
B

Bob Grommes

Hi Robin,

I wonder if one couldn't create a value type that only allows itself to
be assigned to once? That wouldn't provide the syntax sugar you crave,
nor the compile-time notification of any transgression, nor any IL
optimization opportunities. But it would provide the runtime
functionality anyway, and the intent would show in the code by the type
you're declaring (e.g., ReadOnlyInt32).

--Bob
 
J

Jon Skeet [C# MVP]

Bob Grommes said:
I wonder if one couldn't create a value type that only allows itself to
be assigned to once? That wouldn't provide the syntax sugar you crave,
nor the compile-time notification of any transgression, nor any IL
optimization opportunities. But it would provide the runtime
functionality anyway, and the intent would show in the code by the type
you're declaring (e.g., ReadOnlyInt32).

No, because it's not the *value* which is assigned to - it's the
*variable*. You tend to be creating a new value each time (with value
types), not changing an old one.
 
J

Jon Skeet [C# MVP]

Let me offer some (admittedly subjective) justification then for why I think
it would be a positive change to have local 'readonly's.

Excellent - this is more like it :)
First, they provide a useful means to communicate intent. When I'm reading
someone's code and I see 'readonly' it tells me that the author intended
this variable to be immutable. Many of us try to use "meaningful variable
names" because their use facilitates understanding of code intent.
'readonly' locals would serve the exact same purpose.

True - although I believe to a lesser extent. I can't remember
situations where I've been confused as to whether ot not a variable is
really meant to vary within the method - at least not where it matters.
Second, it could help in code correctness. If I declare a variable as
readonly and then I later attempt to change it, I've made an incorrect
assumption somewhere and the compiler will tell me -- either I should not
have declared the variable as 'readonly' or I may be changing the wrong
variable or my understanding of the problem may not be correct.

True, certainly - but likewise, I can't remember the last time I
encountered a bug where this was the cause. Could you give a real-world
example of where this has caused you an issue?

It would certainly be *elegant* to be able to give the compiler this
information, but I'm not personally convinced that it would have
significant real-world benefits.
Thirdly (and let me offer this one with a grain of salt), 'readonly' locals
may allow better IL generation. John, you're right that Java allows an
equivalent qualifier (final) on local variables. Unless I'm mistaken,
declaring a variable as 'final' in Java allowed the Java JITter (Hotspot) to
generate more efficient code.

This *shouldn't* be the case. The compiler must be able to tell if
they're assigned to more than once, as otherwise we wouldn't be able to
get the second point's benefits. If there are performance gains to be
had from working out whether a variable is assigned to more than once,
they should be achievable without explicitly telling the compiler that.
Now, I may be completely wrong about the third point or perhaps it's a point
that does not even apply to C#/CLR. Even so, I think the first two points
are still valid and are advantages we harvest if 'readonly' locals are
allowed. Whether the advantages of 'readonly' locals outweigh the added
complexity they bring to the spec is an open question.

Glad to hear you think so too :) I'm not trying to give my view as a
definitive "it would be useless", just an opinion that its usefulness
doesn't merit the added complexity. (I don't believe the added
complexity is particularly huge either, btw.)
My main motivation for the original post was to discover whether there was
some intrinsic technical issue that precluded their existence and from the
responses so far, it seems here is not.

No, I can't see any technical reasons.
 
R

Robin Bowning

Jon Skeet said:
Excellent - this is more like it :)


True - although I believe to a lesser extent. I can't remember
situations where I've been confused as to whether ot not a variable is
really meant to vary within the method - at least not where it matters.


True, certainly - but likewise, I can't remember the last time I
encountered a bug where this was the cause. Could you give a real-world
example of where this has caused you an issue?

It would certainly be *elegant* to be able to give the compiler this
information, but I'm not personally convinced that it would have
significant real-world benefits.

I think if we're looking for real-world benefits (as we should), we need to
step back and ask ourselves, "Why does C# provide the 'readonly' qualifier
in the first place? Why does the keyword even exist?" Is it solely to guard
against consumers of our classes changing variables we don't want them to
change? Probably not -- for that, we have Properties. Whatever benefits are
realized in using 'readonly' on class-level variables, I would maintain can
be realized on local variables as well. Like many language features, there
is a fair amount of subjectivity and opinion that comes into play.



In terms of making C# more complicated, I think it might actually simplify
things from the programmer's perspective as today the usage of 'readonly'
and 'const' are not symmetric (i.e., local 'const' is allowed while local
'readonly' is not).



So, for what it's worth. I am one developer voting for local 'readonly's.




<snip snip snip>
 
J

Jon Skeet [C# MVP]

Robin Bowning said:
I think if we're looking for real-world benefits (as we should), we need to
step back and ask ourselves, "Why does C# provide the 'readonly' qualifier
in the first place? Why does the keyword even exist?" Is it solely to guard
against consumers of our classes changing variables we don't want them to
change? Probably not -- for that, we have Properties. Whatever benefits are
realized in using 'readonly' on class-level variables, I would maintain can
be realized on local variables as well.

There's a big difference. Within a well-written method, it's usually
very easy to see all the possible assignments to a variable, preferably
all at the same time (i.e. the whole method on the screen at once).
That's not the case for the class as a whole.

Basically, I believe we need more help to understand and maintain
things at a class level than at a method level.
Like many language features, there
is a fair amount of subjectivity and opinion that comes into play.
Certainly.

In terms of making C# more complicated, I think it might actually simplify
things from the programmer's perspective as today the usage of 'readonly'
and 'const' are not symmetric (i.e., local 'const' is allowed while local
'readonly' is not).

It would address the asymmetry, but it would be adding complexity to
the language specification (which currently doesn't need to describe
the behaviour at all).

Now, when it comes to const: do you currently use it in your C# code?
For the types where you're allowed to use it, that should be good
enough, right? I can't remember ever seeing it in any code - do you use
it extensively yourself?
So, for what it's worth. I am one developer voting for local 'readonly's.

Fairly obviously given my posts, I don't consider the change to be
worth making. But it's good to have the discussion.
 
R

Robin Bowning

Jon Skeet said:
There's a big difference. Within a well-written method, it's usually
very easy to see all the possible assignments to a variable, preferably
all at the same time (i.e. the whole method on the screen at once).
That's not the case for the class as a whole.


It would address the asymmetry, but it would be adding complexity to
the language specification (which currently doesn't need to describe
the behaviour at all).

I think the spec actually *does* address it (although somewhat
implicitly) -- the title of Section 10.4.2 is, "Readonly fields". The key
word here is "fields", which of course are not local. So, the current spec
is in effect saying, "readonlys cannot be local".

Now, when it comes to const: do you currently use it in your C# code?
For the types where you're allowed to use it, that should be good
enough, right? I can't remember ever seeing it in any code - do you use
it extensively yourself?

So, it seems that basically you don't think the "added complexity" to the
spec justifies what you see as an insignificant win in programmer intent and
code correctness, whereas I think it does. Fair enough.

Incidentally, yes, I do use 'const' -- I use it everywhere I can. I think it
adds an extra level of clarity (and allows the compiler to check my intent)
and this, as I've mentioned, is what I think 'readonly' locals would bring
to the table as well.

Even if we disagree I also appreciate the discussion.
 
J

Jon Skeet [C# MVP]

Robin Bowning said:
I think the spec actually *does* address it (although somewhat
implicitly) -- the title of Section 10.4.2 is, "Readonly fields". The key
word here is "fields", which of course are not local. So, the current spec
is in effect saying, "readonlys cannot be local".

Well, they're not entirely the same though - you'd have to specify what
behaviour you wanted for readonly fields. Would they have to be
initialised at the point of declaration, or would the compiler have to
check that they were only assigned to once? For fields it's a case of
"constructor or variable initializer" but for locals you'd need to
specify it slightly differently.

Not a huge blow, of course.
So, it seems that basically you don't think the "added complexity" to the
spec justifies what you see as an insignificant win in programmer intent and
code correctness, whereas I think it does. Fair enough.

Yup, I think that's the crux of it, basically.
Incidentally, yes, I do use 'const' -- I use it everywhere I can. I think it
adds an extra level of clarity (and allows the compiler to check my intent)
and this, as I've mentioned, is what I think 'readonly' locals would bring
to the table as well.

Interesting. I can't say I've seen any similar code, but that doesn't
make it "bad" in any way. (I use const, of course, but not for locals.
Even if we disagree I also appreciate the discussion.

Likewise.
 

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