24

C# compiler gave me the following error

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

Do I have to move the code (in my private function) into the constructor? That sounds awkward.

Note that the private method was intended only to be called by the constructor. I expect that there is some sort of attribute that I can use to mark the method corresponding.

tom
  • 14,273
  • 19
  • 65
  • 124

6 Answers6

33

Despite what the other posts are saying, there is actually a (somewhat unusual) way to do this and actually assign the value in a method:

public class Foo
{
    private readonly string _field;

    public Foo(string field)
    {
        Init(out _field, field);
    }

    private static void Init(out string assignTo, string value)
    {
        assignTo = value;
    }
}

Example derived from here.

Alternatively, you can also return the value from a private method and assign it in the constructor as follows:

class Foo
{
    private readonly string _field;

    public Foo()
    {
        _field = GetField();
    }

    private string GetField()
    {
        return "MyFieldInitialization";
    }
}
Community
  • 1
  • 1
Zaid Masud
  • 13,225
  • 9
  • 67
  • 88
  • 1
    This is the closest solution to op's question. Though, as how I understand his request, he wants the method to only be "callable" by the constructor. That however is to my knowledge not possible yet. – baltermia Mar 02 '21 at 13:38
  • Also works with `ref` instead of `out`, in case your `Init` method might not assign a value. – Heath Raftery Sep 03 '22 at 14:58
6

Readonly field can only be assigned by the constructor. What you can do is to initialize the field with a method:

class Foo
{
    private readonly Bar _bar = InitializeBar();

    private Bar InitializeBar()
    {
        // Add whatever logic you need to obtain a Foo instance.
        return new Bar();
    }
}
Antoine Aubry
  • 12,203
  • 10
  • 45
  • 74
4

Yes. Have you tried constructor chaining as an alternative to using a common method?

public StuffClass(string a, char b, int c)
{
    _a = a;
    _b = b;
    _c = c;
}

public StuffClass(string a, char b)
   : this(a, b, 2) 
{}
Ritch Melton
  • 11,498
  • 4
  • 41
  • 54
  • The private method was intended only to be called by the constructor. I expect that there is some sort of attribute that I can use to mark the method corresponding. – tom Jul 27 '11 at 17:31
  • @tom - I don't understand what you mean about the attribute, but constructor chaining is an idiomatic C# way of doing what you are describing. – Ritch Melton Jul 27 '11 at 19:17
1

The readonly members can only assigned in the class level or on its constructor. that is the benefit from using the readonly keyword.

class Foo
{
    private readonly Foo _foo = new Foo(); // Valid

    public Foo()
    {
        _foo = new Foo(); // Valid
    }

    private void SomeMethod()
    {
        _foo = new Foo(); // Not valid
    }
}

You can use readonly as alternative to the const keyword when using classes "other that the string class", because the compiler will not allow you to assign a const to a classes.

Dan Abramov
  • 264,556
  • 84
  • 409
  • 511
Jalal Said
  • 15,906
  • 7
  • 45
  • 68
0

If you want to modify it you should not make it read only in the first place. Once a variable is read only you can modify it only in constructor or at declaration time as error suggests

According to MSDN

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.

Dan Abramov
  • 264,556
  • 84
  • 409
  • 511
Haris Hasan
  • 29,856
  • 10
  • 92
  • 122
-1

You can literally paste "{ get; private set; }" in front of each equals sign in your readonly declarations to achieve almost the same thing (property can now be set in anywhere in class not just in constructor but at least its not changeable outside class). This is strictly true for value types but not reference types in which readonly might have an advantage.

class Foo
{
    // public readonly MyInt = 30;
    public int MyInt { get; private set; } = 30;
}