Why can\'t I initialize readonly variables in a initializer? The following doesn\'t work as it should:
class Foo
{
public readonly int bar;
}
new Foo {
What you're trying to do is this:
class Foo
{
public readonly int bar;
Foo(int b)
{
bar = b; // readonly assignments only in constructor
}
}
Foo x = new Foo(0);
Allowing a readonly
to be set in an initializer introduces contradictions and complications that can't be enforced at compile-time. I imagine the restriction is to avoid ambiguity. The big key is compile-time validation.
Imagine this:
class Foo
{
public readonly int bar;
Foo () {
// compiler can ensure that bar is set in an invoked ctor
bar = 0;
}
}
// compiler COULD know that `bar` was set in ctor
// and therefore this is invalid
new Foo { bar = 0; }
Now, consider:
class Foo
{
public readonly int bar;
Foo () {
// imagine case where bar not set in ctor
}
}
// compiler COULD know that `bar` is not bound yet
// therefore, this COULD be valid
new Foo { bar = 0; }
// but this COULD be proved to never be valid
new Foo();
Imagine that both of the above cases are unified (say, "by compiler magic"), however, enter in generics:
T G<T> () where T : new
{
// What in heck should happen *at compile time*?
// (Consider both cases above.)
// What happens if T (Foo) changes to include/not-include setting the
// readonly variable in the ctor?
// Consider intermediate code that invokes G<Foo>() and this other
// code is NOT recompiled even though Foo is--
// Yet a binary incompatibility has been added!
// No thanks!
return new T();
}
G<Foo>();
I believe the cases I have outlined show some complications of using a "dynamic" readonly
approach and, at the end of the day, I believe it is merely a chosen language restriction (compilers implement languages) to enforce/allow compile-time validation.
Since readonly
variables must be initialized in constructor, and property initializers execute after the construction of object, that is not valid.
Because you specified it is readonly. It does not make sense to specify that something is readonly then expect a write statement to work.
This is a result of the implementation of the readonly keyword. The quote below is taken from the MSDN reference for readonly:
The readonly keyword is a modifier that you can use on fields. When a field declaration includes a readonly modifier, assignments to the fields introduced by the declaration can only occur as part of the declaration or in a constructor in the same class.
The initializer is just syntactic sugar. When you write:
new Foo { bar=0; };
(Which, by the way, is a syntax error and should be this...)
new Foo { bar=0 }
what's actually happening is:
var x = new Foo();
x.bar = 0;
Since the property is read-only, that second statement is invalid.
Edit: Based on your edit, the question is a little unclear. A readonly
property is, by design, not settable. It's built at object construction. This is enforced by both the compiler and the runtime. (Admittedly, I haven't tested the latter, since it would take some trickery to get around the former.)
Keep in mind that there are two stages of "compilation." It's enforced when compiling the C# code into IL code, and it's enforced when compiling the IL code into machine code.
It's not a technical limit of the CLR, and it's working exactly as it should, given the explicit readonly
declaration. After the object is constructed, you can't set a readonly
property.