Why can't I initialize readonly variables in a initializer?

后端 未结 10 1921
渐次进展
渐次进展 2021-01-17 08:16

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 {          


        
相关标签:
10条回答
  • 2021-01-17 08:33

    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);
    
    0 讨论(0)
  • 2021-01-17 08:34

    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.

    0 讨论(0)
  • 2021-01-17 08:34

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

    0 讨论(0)
  • 2021-01-17 08:35

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

    0 讨论(0)
  • 2021-01-17 08:42

    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.

    0 讨论(0)
  • 2021-01-17 08:43

    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.

    0 讨论(0)
提交回复
热议问题