What is the use of static constructors in C#?

CsharpServer Side ProgrammingProgramming

A static constructor is used to initialize any static data, or to perform a particular action that needs to be performed once only. It is called automatically before the first instance is created or any static members are referenced.

Static constructors are useful when creating wrapper classes for unmanaged code, when the constructor can call the LoadLibrary method. Static constructors are also a convenient place to enforce run-time checks on the type parameter that cannot be checked at compile time via constraints.

Static constructors have the following properties −

  • A static constructor does not take access modifiers or have parameters.

  • A class or struct can only have one static constructor.

  • Static constructors cannot be inherited or overloaded.

  • A static constructor cannot be called directly and is only meant to be called by the common language runtime (CLR). It is invoked automatically.

  • The user has no control on when the static constructor is executed in the program.

  • A static constructor is called automatically to initialize the class before the first instance is created or any static members are referenced. A static constructor will run before an instance constructor. A type's static constructor is called when a static method assigned to an event or a delegate is invoked and not when it is assigned. If static field variable initializers are present in the class of the static constructor, they will be executed in the textual order in which they appear in the class declaration immediately prior to the execution of the static constructor.

  • If you don't provide a static constructor to initialize static fields, all static fields are initialized to their default value as listed in Default values of C# types.

  • If a static constructor throws an exception, the runtime will not invoke it a second time, and the type will remain uninitialized for the lifetime of the application domain in which your program is running. Most commonly, a TypeInitializationException exception is thrown when a static constructor is unable to instantiate a type or for an unhandled exception occurring within a static constructor. For implicit static constructors that are not explicitly defined in source code, troubleshooting may require inspection of the intermediate language (IL) code.

  • The presence of a static constructor prevents the addition of the BeforeFieldInit type attribute. This limits runtime optimization.

  • A field declared as static readonly may only be assigned as part of its declaration or in a static constructor. When an explicit static constructor is not required, initialize static fields at declaration, rather than through a static constructor for better runtime optimization.

Example

 Live Demo

using System;
namespace DemoApplication{
   public class Program{
      static void Main(string[] args){
         Car user = new Car();
         Car user1 = new Car();
         Console.ReadLine();
      }
   }
   public class Car{
      static Car(){
         Console.WriteLine("Static constructor called");
      }
      public Car(){
         Console.WriteLine("Default constructor called");
      }
   }
}

Output

Static constructor called
Default constructor called
Default constructor called

In the above example we could see that the static constructor is called only once.

Example

 Live Demo

using System;
using System.Threading;
namespace DemoApplication{
   public class Car{
      protected static readonly DateTime globalStartTime;
      protected int RouteNumber { get; set; }
      static Car(){
         globalStartTime = DateTime.Now;
         Console.WriteLine($"Static constructor called. Global start time:
         {globalStartTime.ToLongTimeString()}");
      }
      public Car(int routeNum){
         RouteNumber = routeNum;
         Console.WriteLine($"Car {RouteNumber} is created.");
      }
      public void Drive(){
         TimeSpan elapsedTime = DateTime.Now - globalStartTime;
         Console.WriteLine($"Car {this.RouteNumber} is starting its route
         {elapsedTime.Milliseconds} minutes after global start time
         {globalStartTime.ToShortTimeString()}.");
      }
   }
   class TestCar{
      static void Main(){
         Car car1 = new Car(1);
         Car car2 = new Car(2);
         car1.Drive();
         Thread.Sleep(25);
         car2.Drive();
         Console.ReadLine();
      }
   }
}

Output

Static constructor called. Global start time:
7:09:06 AM
Car 1 is created.
Car 2 is created.
Car 1 is starting its route25 minutes after global start time7:09 AM.
Car 2 is starting its route50 minutes after global start time7:09 AM.
raja
Published on 24-Sep-2020 16:18:01
Advertisements