2 out of 2 rated this helpful - Rate this topic

readonly (C# Reference)

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.

In this example, the value of the field year cannot be changed in the method ChangeYear, even though it is assigned a value in the class constructor:


    class Age
    {
        readonly int _year;
        Age(int year)
        {
            _year = year;
        }
        void ChangeYear()
        {
            //_year = 1967; // Compile error if uncommented.
        }
    }



You can assign a value to a readonly field only in the following contexts:

  • When the variable is initialized in the declaration, for example:

    public readonly int y = 5;
    
  • For an instance field, in the instance constructors of the class that contains the field declaration, or for a static field, in the static constructor of the class that contains the field declaration. These are also the only contexts in which it is valid to pass a readonly field as an out or ref parameter.

Note Note

The readonly keyword is different from the const keyword. A const field can only be initialized at the declaration of the field. A readonly field can be initialized either at the declaration or in a constructor. Therefore, readonly fields can have different values depending on the constructor used. Also, while a const field is a compile-time constant, the readonly field can be used for runtime constants as in the following example:

public static readonly uint timeStamp = (uint)DateTime.Now.Ticks;

    public class ReadOnlyTest
    {
       class SampleClass
       {
          public int x;
          // Initialize a readonly field
          public readonly int y = 25;
          public readonly int z;

          public SampleClass()
          {
             // Initialize a readonly instance field
             z = 24;
          }

          public SampleClass(int p1, int p2, int p3)
          {
             x = p1;
             y = p2;
             z = p3;
          }
       }

       static void Main()
       {
          SampleClass p1 = new SampleClass(11, 21, 32);   // OK
          Console.WriteLine("p1: x={0}, y={1}, z={2}", p1.x, p1.y, p1.z);
          SampleClass p2 = new SampleClass();
          p2.x = 55;   // OK
          Console.WriteLine("p2: x={0}, y={1}, z={2}", p2.x, p2.y, p2.z);
       }
    }
    /*
     Output:
        p1: x=11, y=21, z=32
        p2: x=55, y=25, z=24
    */



In the preceding example, if you use a statement like this:

p2.y = 66; // Error

you will get the compiler error message:

The left-hand side of an assignment must be an l-value

which is the same error you get when you attempt to assign a value to a constant.

For more information, see the C# Language Specification. The language specification is the definitive source for C# syntax and usage.

Did you find this helpful?
(1500 characters remaining)
Community Content Add
Annotations FAQ
Different error coming on execution of the example.
Hi,  $0I was working on the last example of this article. When I tried to execute the following steps :$0 $0$0 $0 $0In the preceding example, if you use a statement like this: $0 $0p2.y = 66; // Error$0 $0====================================$0 $0Code from example$0 $0====================================$0 $0SampleClass p2 = new SampleClass();$0 $0p2.x = 55;   // OK$0 $0p2.y = 66;  // Error$0 $0------------------------------------$0 $0I got the following error:$0 $0readonly field cannot be assigned to (except in a constructor or a variable initializer) and not the one mentioned in the article: The left-hand side of an assignment must be an l-value $0 $0Please let me know if I am doing something wrong or else correct the error message as its a bit misleading.$0 $0Additional Environment details:$0 $0IDE: VS 2010 $0 $0Target Framwork: 4.0$0 $0$0 $0 $0Regards,$0 $0Ashwani$0
Re: Suggestion Reply
Thanks, I know, although it's not exactly the same, since readonly fields cannot be assigned in a procedure that's not a constructor, even within the class. True, it's not as necessary to protect data from your own class... But since it's possible for fields, it can be argued that it could be applied to properties as well. It's really marginal. Thanks again.
Suggestion Reply
You can have a "readonly" auto property by doing that:

public MyType MyProperty { get; private set; }

It's not read-only, but it can only be assigned in the class since the setter is private.
Suggestion

It wouldn't be bad if readonly could be used with properties as well as fields. The only purpose of course would be avoiding the need for boilerplate hidden fields, just like (and in conjunction with) default accessors. For example:


public readonly bool YesNo { get; set; }


instead of

private readonly bool _YesNo;
public bool YesNo { get { return _YesNo; } }


I'm aware that public and readonly seem to contradict each other, but so do they when used in fields, as they currently can be used, and everybody understands that readonly makes public irrelevant when assigning.

Of course declaring readonly a property with no set accessor would be a compile-time error.