readonly keyword
- by nmarun
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:
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”
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.