static constructor in C-Sharp / C#

A typical constructor is used to set the value of an object’s instance-level data at the time of creation.
However, what would happen if you attempted to assign the value of a static point of data in a typical constructor?
You might be surprised to find that the value is reset each time you create a new object!
To illustrate, assume you have updated the SavingsAccount  class constructor as follows (also note we are no longer assigning the currInterestRate field inline):

Code Snippet
  1. class SavingsAccount
  2. {
  3.   public double currBalance;
  4.   public static double currInterestRate;
  6.   // Notice that our constructor is setting
  7.   // the static currInterestRate value.
  8.   public SavingsAccount(double balance)
  9.   {
  10.     currInterestRate = 0.04;  // This is static data!
  11.     currBalance = balance;
  12.   }
  13. ...
  14. }

Now, assume you have authored the following code in Main():

Code Snippet
  1. static void Main( string[] args )
  2. {
  3.   Console.WriteLine("***** Fun with Static Data *****\n");
  5.   // Make an account.
  6.   SavingsAccount s1 = new SavingsAccount(50);
  8.   // Print the current interest rate.
  9.   Console.WriteLine("Interest Rate is: {0}", SavingsAccount.GetInterestRate());
  11.   // Try to change the interest rate via property.
  12.   SavingsAccount.SetInterestRate(0.08);
  14.   // Make a second account.
  15.   SavingsAccount s2 = new SavingsAccount(100);
  17.   // Should print 0.08...right??
  18.   Console.WriteLine("Interest Rate is: {0}", SavingsAccount.GetInterestRate());
  19.   Console.ReadLine();
  20. }

If you execute the previous Main() method, you would see that that the currInterestRate variable is
reset each time you create a new SavingsAccount object, and it is always set to 0.04. Clearly, setting the
value of static data in a normal instance-level constructor sort of defeats the whole purpose. Every time
you make a new object, the class-level data is reset! One approach to setting a static field is to use
member initialization syntax, as you did originally:

Code Snippet
  1. class SavingsAccount
  2. {
  3.   public double currBalance;
  5.   // A static point of data.
  6.   public static double currInterestRate = 0.04;
  7. ...
  8. }

This approach will ensure the static field is assigned only once, regardless of how many objects you
create. However, what if the value for your static data needed to be obtained at runtime? For example, in
a typical banking application, the value of an interest rate variable would be read from a database or
external file. To perform such tasks requires a method scope such as a constructor to execute the code
For this very reason, C# allows you to define a static constructor, which allows you to safely set the
values of your static data. Consider the following update to our class:

Code Snippet
  1. class SavingsAccount
  2. {
  3.   public double currBalance;
  4.   public static double currInterestRate;
  6.   public SavingsAccount(double balance)
  7.   {
  8.     currBalance = balance;
  9.   }
  11.   // A static constructor!
  12.   static SavingsAccount()
  13.   {
  14.     Console.WriteLine("In static ctor!");
  15.     currInterestRate = 0.04;
  16.   }
  17. ...
  18. }

Simply put, a static constructor is a special constructor that is an ideal place to initialize the values
of static data when the value is not known at compile time (e.g., you need to read in the value from an
external file, a database, generate a random number, or whatnot). If you were to rerun the previous
Main() method, you would find the output you expect. Note that the message “In static ctor!” only prints
out one time, as the CLR calls all static constructors before first use (and never calls them again for that
instance of the application):

***** Fun with Static Data *****
In static ctor!
Interest Rate is: 0.04
Interest Rate is: 0.08 

Here are a few points of interest regarding static constructors:
  • A given class may define only a single static constructor. In other words, the static constructor cannot be overloaded. 
  • A static constructor does not take an access modifier and cannot take any parameters.
  • A static constructor executes exactly one time, regardless of how many objects of the type are created.
  • The runtime invokes the static constructor when it creates an instance of the class or before accessing the first static member invoked by the caller.
  • The static constructor executes before any instance-level constructors. 

Given this modification, when you create new SavingsAccount objects, the value of the static data is preserved, as the static member is set only one time within the static constructor, regardless of the number of objects created.

Post a Comment