Learn About Static In C#

What is Static?

In common run throughs, static means fixed or not changing unless someone changes it. Similarly, in computer programming languages, a static variable is a variable that has been allocated "statically", meaning that value assigned to a static variable remains same throughout the entire run of the program.

Let us understand the concept of static in a simpler way using the below use case: Your brother or sister is studying in class V and there can be a maximum of 30 total students enrolled in his/her classroom.

Consider that the teacher makes a note of the weight and height of each of the student. I ask you one question, does the weight of each one of them have the same value? The answer is No. Each one of them has different values for weight.

Consider if one student consumes more food and puts on weight. Will it affect the value of the weight of all the students? The answer is No. Each one of them has different values for weight.

So, the weight of the student is a non- static variable. Each student has its own value for that.

Let's say, at the beginning of the session, 30 students sign up in your sister or brother’s class. I ask you one question; how many students can be enrolled in the classroom? You will tell me 30. I ask the same question to another student. All will say 30.

After a few months one classmate doesn't like your school and s/he discontinues ... Drops out:)..!!! . I ask the same question; how many students can be enrolled in classroom? You will tell me 30. I ask the same question to another student. All will say 30.

So the maximum number of students that can be enrolled in the class is a static variable that will remain the same throughout the entire run of the program until unless the school administration makes any change to the value.

Static in C#

C# programs includes "static" keywords just like other programming languages such as C++, Java, etc. The Static keyword can be applied on classes, variables, methods, properties, operators, events and constructors. However, it cannot be used with indexers, destructors or types other than classes.

Prefixing the static modifier before classes, variables, methods, properties, operators, events and constructors makes them static, meaning the value assigned to it will remain the same throughout the entire run of the program and can be accessed from anywhere in the program without any object reference provided it has been declared as public.

Static Member Variables

The static member is callable on a class even when no instance of the class has been created. The static member is always accessed by the class name, not the instance name. Only one copy of a static member exists, regardless of how many instances of the class are created.

Scope

In terms of scope and extent, static member variables have the entire run of the program, but may have more limited scope.

Local Variable

Declaring a private static variable in a class makes it non-accessible from another class but it can be accessed from within the class; for example to store the count of instances we can declare a private static variable and public instance property return count of instances.

  1. publicclassStaticVariableClass {  
  2.     ///<summary>  
  3.     /// Default Constructor which increment static variable _numberOfInstances  
  4.     /// which is meant is to store the count of instances of this class  
  5.     ///</summary>  
  6.     public StaticVariableClass() {  
  7.         _numberOfInstances = ++_numberOfInstances;  
  8.     }  
  9.     ///<summary>  
  10.     /// Local Static variable - will not be accessible from  
  11.     /// another class or any method outside this class.  
  12.     /// this variable is to store the count of instances of this class  
  13.     ///</summary>  
  14.     privatestaticint _numberOfInstances = 0;  
  15.     ///<summary>  
  16.     /// Public instance method which returns the value assigned to the  
  17.     /// local static variable _numberOfInstances  
  18.     ///</summary>  
  19.     publicint NumberOfInstances {  
  20.         get {  
  21.             return _numberOfInstances;  
  22.         }  
  23.     }  
  24. }  
  25. Static variable will not be accessible using StaticVariableClass._numberOfInstances directly but will be accessible after creating an object of the class StaticVariableClass.  
  26. classProgram {  
  27.     staticvoid Main(string[] args) {  
  28.         StaticVariableClass staticVariableClassObject = newStaticVariableClass();  
  29.         Console.WriteLine(staticVariableClassObject.NumberOfInstances);  
  30.         Console.ReadLine();  
  31.     }  
  32. }  

As we can see the default constructor increments the value of static variable _numberOfInstances whenever class is instantiated using the new keyword. Output of this program will return 1.

Global Variable

Please note that C# is an object-oriented programming (OOP) language and does not support global variables directly. The solution is to add a static class and declare a public static variable or declare a public static variable in a class makes it accessible from anywhere in the program meaning a global variable. Using a global variable violates the OOP concept a bit, but can be very useful in certain circumstances, for example to store the maximum number of students that can be enrolled in class we can declare a static global variable.

  1. publicstaticclassStaticGlobalVariable {  
  2.     ///<summary>  
  3.     /// Global Static variable – will be accessible from another  
  4.     /// class or any method outside this class  
  5.     /// This variable is to store the count of maximum number of students  
  6.     /// that can be enrolled in the class  
  7.     ///</summary>  
  8.     privatestaticint _maximumNumberOfStudents = 30;  
  9.     ///<summary>  
  10.     /// Public instance method which returns the value assigned to  
  11.     /// the local static variable _maximumNumberOfStudents  
  12.     ///</summary>  
  13.     publicstaticint MaximumNumberOfStudents {  
  14.         get {  
  15.             return _maximumNumberOfStudents;  
  16.         }  
  17.     }  
  18. }  
  19. classProgram {  
  20.     staticvoid Main(string[] args) {  
  21.         Console.WriteLine("maximum students that can be enrolled in a class - {0}", StaticGlobalVariable.MaximumNumberOfStudents);  
  22.         Console.ReadLine();  
  23.     }  
Accessibility/Compatibility

Non Static methods and properties can access both static and instance (non-static) fields and events.

  1. ///<summary>  
  2. /// This is the class that defines and demonstrate Non Static method  
  3. /// access Static field  
  4. ///</summary>  
  5. publicclassNonStaticMethodAccessStaticMember {  
  6.     ///<summary>  
  7.     /// Local Static variable - will not be accessible from  
  8.     /// another class or any method outside this class  
  9.     /// This variable is to store the count of instances of this class  
  10.     ///</summary>  
  11.     privatestaticint _numberOfInstances = 0;  
  12.     ///<summary>  
  13.     /// This is the instance method (non-static method) that  
  14.     /// access local static variable.  
  15.     /// This method compile successfully  
  16.     ///</summary>  
  17.     publicvoid PrintNumberOfInstances() {  
  18.         Console.WriteLine("Number of Instances: {0}", _numberOfInstances);  
  19.     }  
Static methods and properties cannot access non-static fields and events. Otherwise it gives a compilation error - CS0120 An object reference is required for the non-static field, method, or property

  1. ///<summary>  
  2. /// This is the class which act as an instance class meaning  
  3. /// instance of class can be created  
  4. ///</summary>  
  5. publicclassStaticMethodAccessNonStaticMember {  
  6.     ///<summary>  
  7.     /// Local instance variable - will not be accessible from another  
  8.     /// class or any method outside this class  
  9.     /// This variable is to store the count of instances of this class  
  10.     ///</summary>  
  11.     privateint _numberOfInstances = 0;  
  12.     ///<summary>  
  13.     /// This is the instance method which access local static variable.  
  14.     /// This method compile successfully  
  15.     ///</summary>  
  16.     publicstaticvoid StaticPrintNumberOfInstances() {  
  17.         Console.WriteLine("Number of Instances: {0}", _numberOfInstances);  
  18.     }  
  19. }  

On Compilation the above code gives the below error:

  • Static methods and properties cannot access an instance variable of any object
  • Static methods and properties can access instance variable of any object if passed in a method parameter explicitly.
    1. publicclassRegistration {  
    2.     privateStudent _selectedStudent = null;  
    3.     privateCourse _selectedCourse = null;  
    4.     ///<summary>  
    5.     /// Dummy Students data  
    6.     ///</summary>  
    7.     privatereadonlyList < Student > _students = newList < Student > () {  
    8.         newStudent() {  
    9.                 StudentId = 1, FirstName = "Hemant", LastName = "Jindal"  
    10.             },  
    11.             newStudent() {  
    12.                 StudentId = 2, FirstName = "Titiksha", LastName = "Jindal"  
    13.             }  
    14.     };  
    15.     ///<summary>  
    16.     /// Dummy Courses data  
    17.     ///</summary>  
    18.     privatereadonlyList < Course > _courses = newList < Course > () {  
    19.         newCourse() {  
    20.                 CourseId = 1, CourseName = "Computer Programming"  
    21.             },  
    22.             newCourse() {  
    23.                 CourseId = 2, CourseName = "Artifical Intelligence"  
    24.             },  
    25.     };  
    26.     ///<summary>  
    27.     /// This method access static method defined in another class and  
    28.     /// pass instance variable of an object  
    29.     ///</summary>  
    30.     ///<param name="studentId"></param>  
    31.     ///<param name="courseId"></param>  
    32.     publicvoid Register(int studentId, int courseId) {  
    33.         //basis on student identifier retrieve a student from students  
    34.         _selectedStudent = _students.FirstOrDefault(x => x.StudentId == studentId);  
    35.         //basis on course identifier retrieve a course from available courses  
    36.         _selectedCourse = _courses.FirstOrDefault((c => c.CourseId == courseId));  
    37.         StudentCourseEnrollment.Enroll(_selectedStudent, _selectedCourse);  
    38.     }  
    39. }  
    40. ///<summary>  
    41. /// This is the class that defines and demonstrate Static method  
    42. /// access instance variable of any object if passed in a  
    43. /// method parameter explicitly  
    44. ///</summary>  
    45. publicclassStudentCourseEnrollment {  
    46.     publicstaticvoid Enroll(Student student, Course course) {  
    47.         Console.WriteLine("{0} is enrolled to the course {1}", student.FirstName, course.CourseName);  
    48.     }  
    49. }  
Access Modifiers
  • Static members in non-static class can be marked as public, protected, internal. It is always recommended to use public because static members cannot be accessed using instance
  • Static members in non-static and static class cannot be overridden meaning cannot be marked as Virtual, Abstract, or override. Doing so gives a compilation error - CS0112 A static member cannot be marked as override, virtual, or abstract
    1. publicclassBaseClass {  
    2.     ///<summary>  
    3.     /// Static methods cannot be marked as Virtual  
    4.     ///</summary>  
    5.     publicstaticvirtualvoid StaticMethod() {}  
    6. }  
    7. ///<summary>  
    8. /// This class is derived from another class BaseClass  
    9. ///</summary>  
    10. publicclassDerivedClass: BaseClass {  
    11.     ///<summary>  
    12.     /// Static methods cannot be overridden  
    13.     ///</summary>  
    14.     publicoverridevoid StaticMethod() {}  
    15. }  
  • Static methods in class can be overloaded.
    1. publicclassOverloadedStaticMethods {  
    2.     publicstaticint AddNumbers(int number1, int number2) {  
    3.         Console.WriteLine("Method with two parameters");  
    4.         return number1 + number2;  
    5.     }  
    6.     publicstaticint AddNumbers(int number1, int number2, int number3) {  
    7.         Console.WriteLine("Method with three parameters");  
    8.         return number1 + number2 + number3;  
    9.     }  
    10. }  
Static Class

A static class is basically the same as a non-static class, except static class does not maintain any data, state and behavior which means that static class is stateless. A static class can be used as a convenient container for sets of methods that just operate on input parameters and do not have to get or set any internal instance fields. An example of static class can be a class to define Interest calculator, EMI calculator, Temperature Conversion, logging error/message and displaying a message on GUI.

  • Static classes can have only static fields/members and static methods.
  • Static classes are implicitly abstract (i.e. they're compiled to IL which describes an abstract class) but you can't add the abstract modifier yourself. Doing so gives a compilation error - CS0418 an abstract class cannot be sealed or static,
    1. publicabstractstaticclassAbstractStaticClass  
    2. {  
    3. }  
  • Static class object can neither be created nor instantiated. Doing so gives a compilation error - CS0712 Cannot create an instance of the static class and CS0723 Cannot declare a variable of static type
    1. classProgram {  
    2.     staticvoid Main(string[] args) {  
    3.         //This statement gives a compilation error -  
    4.         //CS0712 Cannot create an instance of the static class and  
    5.         //CS0723 Cannot declare a variable of static type  
    6.         SampleClass sampleClassObject = newSampleClass();  
    7.     }  
    8. }  
    9. staticclassSampleClass {}  
  • Static classes always derives from object. They can be neither inherited nor derived meaning they cannot be a part of inheritance. Doing so gives a compilation error - CS0713. One possible reason is that .net CLR maintains only one copy of static members or class per application domain
    1. staticclassBaseClass {}  
    2. ///<summary>  
    3. /// This decalration gives a compilation error -  
    4. /// CS0713 Static classes must derive from object.  
    5. ///</summary>  
    6. staticclassDerivedClass: BaseClass {}  
    7. ///<summary>  
    8. /// This decalration gives a compilation error -  
    9. /// CS0709 cannot derive from static class  
    10. ///</summary>  
    11. classNonStaticDerivedClass: BaseClass {}  
Static Constructor
  • Static constructor is used to initialize static data members as soon as the class is referenced the first time.
  • Static constructor can be defined within non-static class.
  • Static constructor for a class executes at most one time during a single program instantiation
    1. publicclassDemoInitializeStaticDataMembers {  
    2.     privatestaticreadonlystring StaticVariable;  
    3.     ///<summary>  
    4.     ///  
    5.     ///</summary>  
    6.     static DemoInitializeStaticDataMembers() {  
    7.         StaticVariable = "My Name is StaticVariable and I am initialized only once";  
    8.         Console.WriteLine(StaticVariable);  
    9.     }  
    10.     ///<summary>  
    11.     /// Local Static variable - will not be accessible from another  
    12.     /// class or any method outside this class  
    13.     /// This variable is to store the count of instances of this class  
    14.     ///</summary>  
    15.     privatestaticint _numberOfInstances = 0;  
    16.     public DemoInitializeStaticDataMembers() {  
    17.         _numberOfInstances = ++_numberOfInstances;  
    18.         Console.WriteLine("Instance Number: {0}", _numberOfInstances);  
    19.     }  
    20. }  
    21. staticvoid Main(string[] args) {  
    22.     DemoInitializeStaticDataMembers objectOne = newDemoInitializeStaticDataMembers();  
    23.     DemoInitializeStaticDataMembers objectTwo = newDemoInitializeStaticDataMembers();  
    24.     // Keep the console window open in debug mode.  
    25.     System.Console.WriteLine("Press any key to exit.");  
    26.     System.Console.ReadKey();  
    27. }  

Output

My Name is StaticVariable and I am initialized only once

"Instance Number: 1"

"Instance Number: 2"

  • Static Constructor defined within the child class executes well before static constructor defined in the parent class but executes once. In the below example we have defined a class named “BaseClass” and another class named “DerivedClass” inheriting BaseClass. We have defined static constructor in both of these classes. Now we will see the output of these static constructors defined
    1. publicclassBaseClass {  
    2.     ///<summary>  
    3.     /// Static Constructor defined with in the BaseClass  
    4.     ///</summary>  
    5.     static BaseClass() {  
    6.         Console.WriteLine("Hi! I am static class constructor defined in BaseClass");  
    7.     }  
    8. }  
    9. publicclassDerivedClass: BaseClass {  
    10.     ///<summary>  
    11.     /// Static Constructor defined with in the DerivedClass derived from BaseClass  
    12.     ///</summary>  
    13.     static DerivedClass() {  
    14.         Console.WriteLine("Hi! I am static class constructor defined in DerivedClass");  
    15.     }  
    16. }  
    17. staticvoid Main(string[] args) {  
    18.     BaseClass baseClassObject = newDerivedClass();  
    19.     // Keep the console window open in debug mode.  
    20.     System.Console.WriteLine("Press any key to exit.");  
    21.     System.Console.ReadKey();  
    22. }  

 

Output

"Hi! I am static class constructor defined in DerivedClass"

"Hi! I am static class constructor defined in BaseClass"

  • Static Constructor executes instance constructor and only executes once. In the below example we have static constructor and instance constructor defined in the class. Now we will see the output of these static constructors and instance constructors defined.
    1. publicclassBaseClass {  
    2.     ///<summary>  
    3.     /// Static Constructor defined with in the BaseClass  
    4.     ///</summary>  
    5.     static BaseClass() {  
    6.         Console.WriteLine("Hi! I am static class constructor defined in BaseClass");  
    7.     }  
    8.     public BaseClass() {  
    9.         Console.WriteLine("Hi! I am Instance class constructor defined in BaseClass");  
    10.     }  
    11. }  
    12. staticvoid Main(string[] args) {  
    13.     BaseClass baseClassObject1 = newBaseClass();  
    14.     BaseClass baseClassObject2 = newBaseClass();  
    15.     // Keep the console window open in debug mode.  
    16.     System.Console.WriteLine("Press any key to exit.");  
    17.     System.Console.ReadKey();  
    18. }  

 

Output

"Hi! I am static class constructor defined in BaseClass"

"Hi! I am Instance class constructor defined in BaseClass"

"Hi! I am Instance class constructor defined in BaseClass"

  • Static Constructor does not have access Modifiers. Doing so gives a compilation error - CS0515 access modifiers are not allowed on static constructors
  • A class can have only one Static Constructor and that too is parameter-less. Doing otherwise gives a compilation error - CS0132: a static constructor must be parameterless
    1. publicclassStaticClassWithTwoConstructor {  
    2.     ///<summary>  
    3.     /// Static Constructor without parameters  
    4.     ///</summary>  
    5.     static StaticClassWithTwoConstructor() {}  
    6.     ///<summary>  
    7.     /// Static Constructor with parameters which gives a compilation error  
    8.     ///</summary>  
    9.     ///<param name="counterValue"></param>  
    10.     static StaticClassWithTwoConstructor(int counterValue) {}  
    11. }  

 

Memory Allocation

C# compiler allocates memory to a static type at compile time unlike instance types, meaning before the associated program is executed.

Scope of static variable is global, meaning these must be available throughout the entire run of the program and they should not be collected by Garbage Collector, these cannot be stored in the stack, as the stack frame will get popped up once the method execution is completed. To overcome this .Net run-time stores the static variables in a special region within the Heap, called High Frequency Heap, which is being used to store objects that are frequently accessed and should not be collected by garbage collector.

The static variable itself is not garbage collected - it is just a memory location that contains a reference to an object. Static fields are considered to be GC roots so any references to them will not be garbage collected as long as the field contains that reference. Note that Objects referenced by static variables will only be garbage collected when the relevant AppDomain is garbage collected or the field is changed to point to a new reference or the field value is set  to null then the object whose reference was stored there becomes eligible for collection.

Also the garbage collector doesn't collect variables, it collects objects. Local and static variables are not part of any object so they are never collected by GC.