8
class foo {
    public readonly int bar;
};
foo a = new foo() { bar = 123 };

error CS0191: A readonly field cannot be assigned to (except in a constructor or a variable initializer)

How can I assign bar in the object initializer above?

Can I initialize readonly members without having to write a custom constructor for every class/struct ?

6 Answers6

8

To summarize the sentiment of the other answers: The error message isn't helpful— object initializers can't be used with readonly fields.

However, constructors with named arguments can, and the syntax to do so is quite similar.  So similar you might even be thinking that you've seen C# object initializers for readonly fields (like I have been) when what you actually saw was this:

class Foo {
    public Foo(int bar) {
        this.bar = bar;
    }
    public readonly int bar;
};

Foo a = new Foo(bar: 123);
// instead of `new Foo() { bar = 123 };`
Slipp D. Thompson
  • 33,165
  • 3
  • 43
  • 43
  • 1
    Exactly! After searching for an hour and reading a lot high voted answers finally the right answer that even makes me understand why I unconsciously just could not believe that initializer lists do not allow assignment to readonly. I still wonder why but named parameters in constructors are just as useful. – Patrick Fromberg Aug 29 '16 at 14:21
7
foo a = new foo() { bar = 123 };

is transformed by the compiler to

foo temp = new foo();
temp.bar = 123;
foo a = temp;

As you can see, the assignment to bar is neither in the foo constructor nor a variable initializer.

So the answer is: you can't.

dtb
  • 213,145
  • 36
  • 401
  • 431
  • 1
    Seems like an oversight from the designers :'( –  Feb 29 '12 at 12:11
  • @tm1rbrt no, there's no oversight - you should just learn about proper encapsulation – scibuff Feb 29 '12 at 12:31
  • @scibuff that seems like a safe, single assignment to me? –  Feb 29 '12 at 12:32
  • 1
    @scibuff I'd consider it an oversight and/or bad design.  In this situation the compiler suggests using a variable initializer.  But that's not a solution to the compiler's problem. – Slipp D. Thompson Jan 22 '14 at 02:28
  • 2
    @scibuff In terms of the language design, I'd consider it bad design that C# structs are considered to be only sane in an immutable form (http://stackoverflow.com/questions/441309/why-are-mutable-structs-evil), yet the language's variable initializer implementation doesn't work with this.  So struct variable initializers are present in the language, but not a Good Part™ because of the CLI. – Slipp D. Thompson Jan 22 '14 at 02:33
1

You pass the value in on the constructor:

public class foo 
{
    public readonly int _bar;

    public foo(int bar) 
    {
        _bar = bar;
    }
};


var x = new foo(12345);

What the compiler is telling you is that the only place you can set your readonly field is in the constructor of the class that holds it, this means:

  • if you need it to change during the lifetime of the object then readonly is not the correct option to use
  • if each instance of the class needs to hold a custom value in the readonly member variable then you need to inject it as part of the constructor

I would suggest that it isn't a good practice to make your readonly field public like this, instead just expose it as a public property that only has a getter.

slugster
  • 49,403
  • 14
  • 95
  • 145
0
class Foo {
     private int bar;

     public Foo( int bar ){
         this.bar = bar;
     }

     public int Bar {
         get { return this.bar; }
     }
}

Foo foo = new Foo( 123 );
scibuff
  • 13,377
  • 2
  • 27
  • 30
0

You can't. You should use the constructor for it. MSDN

Peter Kiss
  • 9,309
  • 2
  • 23
  • 38
0

You can't. What the error wants to tell you that you could use

class foo {
    public readonly int bar = blabla;
};

The object initializer syntax you're using is just syntax sugar for calling the constructor and the assigning to members. And that' not allowed for readonly members.


You will need to introduce a constructor parameter, and then assign in the constructor. C# is pretty lacking concerning syntax sugar for immutable types.

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262