readonly keyword

This is something new that I learned about the readonly keyword. Have a look at the following class:

   1: public class MyClass
   2: {
   3:     public string Name { get; set; }
   4:     public int Age { get; set; }
   5:  
   6:     private readonly double Delta;
   7:  
   8:     public MyClass()
   9:     {
  10:         Initializer();
  11:     }
  12:  
  13:     public MyClass(string name = "", int age = 0)
  14:     {
  15:         Name = name;
  16:         Age = age;
  17:         Initializer();
  18:     }
  19:  
  20:     private void Initializer()
  21:     {
  22:         Delta = 0.2;
  23:     }
  24: }

I have a couple of public properties and a private readonly member. There are two constructors – one that doesn’t take any parameters and the other takes two parameters to initialize the public properties. I’m also calling the Initializer method in both constructors to initialize the readonly member.

Now when I build this, the code breaks and the Error window says:

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

Two things after I read this message:

  1. It’s such a negative statement. I’d prefer something like:
    “A readonly field can be assigned to (or initialized) only in a constructor or through a variable initializer”
  2. But in my defense, I AM assigning it in a constructor (only indirectly). All I’m doing is creating a method that does it and calling it in a constructor.

Turns out, .net was not ‘frameworked’ this way. We need to have the member initialized directly in the constructor. If you have multiple constructors, you can just use the ‘this’ keyword on all except the default constructors to call the default constructor. This default constructor can then initialize your readonly members. This will ensure you’re not repeating the code in multiple places. A snippet of what I’m talking can be seen below:

   1: public class Person
   2: {
   3:     public int UniqueNumber { get; set; }
   4:     public string Name { get; set; }
   5:     public int Age { get; set; }
   6:     public DateTime DateOfBirth { get; set; }
   7:     public string InvoiceNumber { get; set; }
   8:  
   9:     private readonly string Alpha;
  10:     private readonly int Beta;
  11:     private readonly double Delta;
  12:     private readonly double Gamma;
  13:  
  14:     public Person()
  15:     {
  16:         Alpha = "FDSA";
  17:         Beta = 2;
  18:         Delta = 3.0;
  19:         Gamma = 0.0989;
  20:     }
  21:  
  22:     public Person(int uniqueNumber) : this()
  23:     {
  24:         UniqueNumber = uniqueNumber;
  25:     }
  26: }

See the syntax in line 22 and you’ll know what I’m talking about. So the default constructor gets called before the one in line 22. These are known as constructor initializers and they allow one constructor to call another.

The other ‘myth’ I had about readonly members is that you can set it’s value only once. This was busted as well (I recall Adam and Jamie’s show). Say you’ve initialized the readonly member through a variable initializer. You can over-write this value in any of the constructors any number of times.

   1: public class Person
   2: {
   3:     public int UniqueNumber { get; set; }
   4:     public string Name { get; set; }
   5:     public int Age { get; set; }
   6:     public DateTime DateOfBirth { get; set; }
   7:     public string InvoiceNumber { get; set; }
   8:  
   9:     private readonly string Alpha = "asdf";
  10:     private readonly int Beta = 15;
  11:     private readonly double Delta = 0.077;
  12:     private readonly double Gamma = 1.0;
  13:  
  14:     public Person()
  15:     {
  16:         Alpha = "FDSA";
  17:         Beta = 2;
  18:         Delta = 3.0;
  19:         Gamma = 0.0989;
  20:     }
  21:  
  22:     public Person(int uniqueNumber) : this()
  23:     {
  24:         UniqueNumber = uniqueNumber;
  25:         Beta = 3;
  26:     }
  27:  
  28:     public Person(string name, DateTime dob) : this()
  29:     {
  30:         Name = name;
  31:         DateOfBirth = dob;
  32:  
  33:         Alpha = ";LKJ";
  34:         Gamma = 0.0898;
  35:     }
  36:  
  37:     public Person(int uniqueNumber, string name, int age, DateTime dob, string invoiceNumber) : this()
  38:     {
  39:         UniqueNumber = uniqueNumber;
  40:         Name = name;
  41:         Age = age;
  42:         DateOfBirth = dob;
  43:         InvoiceNumber = invoiceNumber;
  44:  
  45:         Alpha = "QWER";
  46:         Beta = 5;
  47:         Delta = 1.0;
  48:         Gamma = 0.0;
  49:     }
  50: }

In the above example, every constructor over-writes the values for the readonly members. This is perfectly valid. There is a possibility that based on the way the object is instantiated, the readonly member will have a different value.

Well, that’s all I have for today and read this as it’s on a related topic.

Published Monday, June 07, 2010 11:19 PM by nmarun
Filed under: ,

Comments

# Twitter Trackbacks for readonly keyword - IBloggable - implemented [asp.net] on Topsy.com

Pingback from  Twitter Trackbacks for                 readonly keyword - IBloggable - implemented         [asp.net]        on Topsy.com

# re: readonly keyword

Tuesday, June 08, 2010 2:08 AM by Pradeep

Thanks a lot, these little things are often ovelooked.

# re: readonly keyword

Tuesday, June 08, 2010 8:56 AM by nmarun

You're welcome Pradeep.

Arun

# re: readonly keyword

Tuesday, June 08, 2010 12:05 PM by Mike Strobel

Yep, there's nothing preventing your helper method from being invoked dynamically at runtime, either directly or through reflection.  The only verifiable way to ensure the fields are readonly is to limit the legal assignment scope to direct field initializers or constructors.

# Markus Tamm » Blog Archive » Links 14.06.2010

Monday, June 14, 2010 3:34 AM by Markus Tamm » Blog Archive » Links 14.06.2010

Pingback from  Markus Tamm  » Blog Archive   » Links 14.06.2010

Leave a Comment

(required) 
(required) 
(optional)
(required)