Fields: when to use "private" or "readonly" in c# ?
Most times we want to protect some fields in our program and as with all things, the situation determines the approach. Encapsulation has always been one of the cornerstones of object-oriented programming (OOP). The ability to choose which state or data we seek to share is what makes the OOP paradigm standout.
Whenever we seek to protect the data or state from outside our class, then using the private access modifier is an ideal choice.
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.IO;
namespace playground
{
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.IO;
namespace playground
{
class Program
{
static void Main(string[] args)
{
var s1 = new MyClass("2018");
//error CS0122: 'MyClass._year' is inaccessible due to its protection level
//System.Console.WriteLine(s1._year);
//output 2018
System.Console.WriteLine(s1.Year);
//change year. sample out will be 202
s1.Changeyear();
System.Console.WriteLine(s1.Year);
}
}
class MyClass
{
private string _year;
public MyClass(string wrd)
{
_year = wrd;
}
//changes the private field _year
public void Changeyear()
{
_year = "2020";
}
public string Year
{
get{return _year; }
set{ _year = value; }
}
}
}
As expected, System.Console.WriteLine(s1._year);
throws an error. However, any method in our class can still make modifications to our program as we saw with the Changeyear()
method we created.
Basically, this shows we can modify the private fields within our class. However, sometimes this may have unintended consequences where changes are mistakenly made to a field.
In other to avoid being able to change set values, the readonly
modifier suffices.
Remember, a readonly field cannot be assigned to except in a constructor of the class or during a variable initializer.
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.IO;
namespace playground
{
class Program
{
static void Main(string[] args)
{
var s1 = new MyClass("2018");
//error CS0122: 'MyClass._year' is inaccessible due to its protection level
// System.Console.WriteLine(s1._year);
//output 2018
System.Console.WriteLine(s1.Year);
//change year
s1.Changeyear();
System.Console.WriteLine(s1.Year);
}
}
class MyClass
{
private string _year;
public MyClass(string wrd)
{
_year = wrd;
}
//changes the private field _year
public void Changeyear()
{
_year = "2020";
}
public string Year
{
get{return _year; }
set{ _year = value; }
}
}
class ReadOnlySample
{
readonly string year;
/* remember we could have just initialized
the year as so:
private string _year = "2018";
However, we will use a constructor.
*/
public ReadOnlySample(string wrd)
{
year = wrd;
}
public void GetYear()
{
System.Console.WriteLine(year);
}
public void ChangeYear()
{
year = "new";
System.Console.WriteLine(year);
}
}
}
The code sample above will not compile if we do not comment out year = "new";
. This is because c# does not permit reassigning readonly
fields after they have been initialized either in a constructor or by variable initialization.
To conclude, whenever you do not want either the class members or classes outside your class to make changes to a field, then use the readonly
modifier. If the goal is to allow the class members alone the ability to make changes, then use the private
modifier.