Why can't I initialize readonly variables in a

2020-04-02 05:09发布

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 { bar=0; }; // does not work

Is this due to some technical limits of the CLR?

EDIT

I know that new Foo { bar=0; } is the same as new Foo().bar=0;, but is "readonly" enforced by the CLR, or is it just a compiler limitation?

10条回答
甜甜的少女心
2楼-- · 2020-04-02 05:30

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.

查看更多
forever°为你锁心
3楼-- · 2020-04-02 05:31

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.

查看更多
家丑人穷心不美
4楼-- · 2020-04-02 05:33

Since readonly variables must be initialized in constructor, and property initializers execute after the construction of object, that is not valid.

查看更多
ら.Afraid
5楼-- · 2020-04-02 05:36

There is not much wrong in your code or assumptions with the exception maybe that it is an important feature of initializer lists to impose no sequence constraints (especially true for C++). The semicolon is a sequencing operator, consequently initializer lists are comma separated instead.

Unless you argue that specifications are correct by definition I believe that the language specification is wrong here. It partly breaks an important feature of the language which is the notion of readonly. The ambiguity problems mentioned in other answers have in my opinion one single underlying cause. Readonly is a very intrusive feature and going half way regarding const correctness is difficult to get right and more importantly, harmful to coding styles developed.

What you are looking for and probably found in the meantime are named arguments: https://stackoverflow.com/a/21273185/2712726 It is not what you asked for but gets near.

Also to be fair, I must add that there are very knowledgeable authors who will totally disagree with these views on const correctness that C++ developers often have. Eric Lippert, who admittedly has brilliant posts has written this (horrifying to C++ developers) statement: https://stackoverflow.com/a/3266579/2712726

查看更多
男人必须洒脱
6楼-- · 2020-04-02 05:37

Because you specified it is readonly. It does not make sense to specify that something is readonly then expect a write statement to work.

查看更多
趁早两清
7楼-- · 2020-04-02 05:38

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);
查看更多
登录 后发表回答