http://www.c-sharpcorner.com/UploadFile/d2fdf5/9-key-concepts-to-keyword-static/
key concept of the keyword static that is worth remembering.
1. Applicability
A class can be static but a structure and interface cannot be. Similarly, constructors, fields, properties and methods can be static but destructors cannot be.
We can have static classes, fields, properties, constructors and methods.
-
- static class StaticClass
- {
-
- }
-
- public class SomeClass
- {
-
- static int intstatic = 0;
-
-
- public static string StaticProperty { get; set; }
-
-
- static SomeClass()
- { }
-
-
- public static void DoSomething()
- {
- Console.WriteLine(intstatic);
- }
- }
But we cannot have static interfaces, structures or destructors.
-
- static interface IStaticInterface
- {
-
- }
-
-
- static struct StaticStruct
- {
-
- }
-
-
- class SomeClass1
- {
-
- static ~SomeClass1()
- { }
- }
If we try to create one, we will get the following compilation error:
Later, we will also explain why such implementation does make sense.
2. Access Modifiers
A static constructor does not have access modifiers. Other static elements do.
We can have static classes, fields, properties and methods denoted with the access modifier. But if you do so with a static constructor as in the following:
-
- public class SomeClass
- {
-
- public static int intstatic = 0;
-
-
- public static string StaticProperty { get; set; }
-
-
- public static SomeClass()
- { }
-
-
- public static void DoSomething()
- {
- Console.WriteLine(intstatic);
- }
- }
It will result in the following compilation error.
Also, if you notice, so far I have used word the constructor but not constructor(s). Why? We will see next.
3. Unique Static Constructor
A class can have only one static constructor and that too is parameterless.
If we use overloading, we can have multiple constructors, each having a different signature. If we try to mark them static as in the following:
- public class SomeClass
- {
-
- static SomeClass()
- {
-
- }
-
-
- static SomeClass(int input)
- {
-
- }
- }
We will get the compilation error:
So, a class cannot have a static constructor with parameter(s) and hence it can have only one static constructor and that is parameterless.
4. Priority - Static vs Instance Constructor
A static constructor executes well before an instance constructor and only executes once.
Let's create one simple program to prove this:
- public class SampleClass
- {
-
- static SampleClass()
- {
- Console.WriteLine("This is SampleClass Static Constructor.");
- }
-
-
- public SampleClass()
- {
- Console.WriteLine("This is SampleClass Instance Constructor.");
- }
- }
-
- class Program
- {
- static void Main()
- {
- SampleClass objC1 = new SampleClass();
- SampleClass objC2 = new SampleClass();
- SampleClass objC3 = new SampleClass();
-
- Console.ReadLine();
- }
- }
Output of this program is as follows:

As you can see, that static constructor was first to execute and only executes once. We will again revisit this point. Especially the words “well before”.
5. Accessibility
Instance members are accessed with a class object outside the class definition and "this" keyword inside the class definition whereas static members can be directly accessed with a class name outside and inside the definition.
This is an important point and it makes sense also since static members are independent of instance objects.
- public class SampleClass {
- public string instanceMsg = "This is instance Field.";
- public static string staticMsg = "This is static Field";
-
- public SampleClass()
- {
-
- Console.WriteLine("Within class instanceMsg:{0}",
- this.instanceMsg);
- Console.WriteLine("Within class staticMsg:{0}",
- SampleClass.staticMsg);
- }
- }
-
- class Program
- {
- static void Main()
- {
- SampleClass ObjS1 = new SampleClass();
-
-
- Console.WriteLine("From Main Program instanceMsg: {0}",
- ObjS1.instanceMsg);
- Console.WriteLine("From Main Program staticMsg: {0}",
- SampleClass.staticMsg);
-
- Console.ReadLine();
- }
- }
We will revisit this in future sections.
6. Compatibility – Static vs Instance members/container
An instance member cannot be created or accessed from a static container whereas static members can be created or accessed from an instance container.
Subheading is not clear! Don't worry. Let's understand this with some examples.
In Scenario 1, we are trying to access the static field
iInc within the instance method
DoSomething().
-
- public class InstanceContainerStaticMember
- {
- static int iInc = 0;
-
-
- public void DoSomething()
- {
-
- iInc++;
- Console.WriteLine("iInc:{0}", iInc);
- }
- }
On the other hand, in Scenario 2, we tried to access an instance member
iInc within the static method
DoSomething().
-
- public class StaticContainerInstanceMember
- {
- int iInc = 0;
-
-
- public static void DoSomething()
- {
-
- iInc++;
- Console.WriteLine("iInc:{0}", iInc);
- }
- }
But when we compiled, Scenario 2 throws the following compilation error.
“An object reference is required for the non-static field, method, or property”
So the compilation error is clear that we cannot access an instance member from a static container. Why? We will explore this with an example. Recall point 5. According to that, static members are referred to with a class name. So in the example below:
- public class SampleClass {
- private int _id;
-
- public SampleClass(int ID)
- {
- _id = ID;
- }
-
- public static void StaticMethod()
- {
-
- }
- }
- class Program
- {
- static void Main()
- {
- SampleClass s1 = new SampleClass(1);
- SampleClass s2 = new SampleClass(2);
- SampleClass s3 = new SampleClass(3);
-
-
- SampleClass.StaticMethod();
- }
- }
We have SampleClass that has a non-static field _id and static method StaticMethod() that wants to access _id. In the Main() program, there are the 3 objects s1, s2 and s3 created of the class SampleClass. And hence the value for _id will be 1, 2 and 3 for the objects s1, s2 and s3 respectively. Now the program makes calls to the SampleClass.StaticMethod(). Since it is called with the class name, if the static method were allowed access to _id, which _id value should it return, s1, s2 or s3? No, it cannot return any sinceStaticMethod() is independent of the class objects and hence independent of instance members and so the compiler shows the error. This holds true for static classes as well. A static class cannot have an instance member such as fields, properties, constructors or methods. Try it yourself!
7. Object creation and Instantiation
A static class object can neither be created nor instantiated.
Since a static class cannot have instance members, it cannot be instantiated. In the example below, we are trying to create an instance of the class SampleClass.
- public static class SampleClass {
-
- }
-
- class Program
- {
- static void Main()
- {
-
- SampleClass s1 = new SampleClass();
- }
- }
We get the compilation error:
Cannot declare a variable of static type 'SampleClass'
Cannot create an instance of the static class ‘SampleClass'
Important
When building an application, you will encounter code blocks that are repetitively used in the application but don't belong to a specific code hierarchy. Usually developers refer to them as utility functions. They serve general utility purposes in the application. You certainly want to modularize such code. At the same time, you want to access these functions without any object creation. Static classes are great to organize these functions. In the Microsoft .NET Framework, one of the great examples of the utility class is the Mathclass. See the screenshot below:
8. Inheritance
A static class cannot be part of an inheritance. It cannot serve as a base class, child class or implement an interface.
Yes that's true. As always, let us see by the following examples.
Case 1: A static class cannot be a base class.
- public static class BaseClass
- {
-
- }
- public class DeriveClass : BaseClass
- {
-
- }
“Cannot derive from static class 'BaseClass'”
Case 2: A static class cannot be a derived class.
- public class BaseClass
- {
-
- }
- public static class DeriveClass : BaseClass
- {
-
- }
“Static class 'DeriveClass' cannot derive from type 'BaseClass'. Static classes must derive from object.”.
Case 3: A static class cannot implement interfaces.
- public interface IInterface
- {
-
- }
- public static class DeriveClass : IInterface
- {
-
- }
“'DeriveClass': static classes cannot implement interfaces”
That's clear except for one question. As we have seen, a static class cannot be a part of an inheritance hierarchy, then what will happen to protected members in the static class? The answer is a static class cannot have protected members. If you try to declare one, it will throw:
- public class BaseClass
- {
- public static virtual void StaticMethod()
- { }
- }
-
- public class DerivedClass : BaseClass
- {
- public override void StaticMethod()
- { }
- }
Compilation error.
“Static classes cannot contain protected members”
In fact, static members in non-static classes cannot be overridden.
- public class BaseClass
- {
- public static virtual void StaticMethod()
- { }
- }
-
- public class DerivedClass : BaseClass
- {
- public override void StaticMethod()
- { }
- }
Compilation error:
“A static member cannot be marked as override, virtual, or abstract”
9. Lifetime
Static elements are in scope as soon as they are referred to in a program for the first time and will remain in scope throughout the life of the AppDomain.
This is an important concept to understand the scope of static elements but I will explain something more than that. Have a look at the example below.
- public class SampleClass
- {
- static int _iCount = 0;
-
- static SampleClass()
- {
- Console.WriteLine("This is Static Ctor");
- }
-
- public void SetValue(int Count)
- {
- _iCount = Count;
- }
-
- public static void Print()
- {
- Console.WriteLine("The value of Count:{0}",
- SampleClass._iCount);
- }
- }
In the class above, we have a static field
_iCount and static method
Print(). In the
Main() program below, we are making a call to the functions
function1() and
function2(). In both of the functions, we are creating an object of the class
SampleClass.
- class Program
- {
- static void Main()
- {
- Console.WriteLine("First line in Main().");
- SampleClass.Print();
- function1();
- function2();
- SampleClass.Print();
- Console.WriteLine("Last line in Main().");
- Console.ReadLine();
- }
-
- public static void function1()
- {
- Console.WriteLine("First line in function1().");
- SampleClass objS2 = new SampleClass();
- objS2.SetValue(1);
- Console.WriteLine("Last line in function1().");
- }
-
- public static void function2()
- {
- Console.WriteLine("First line in function2().");
- SampleClass objS3 = new SampleClass();
- objS3.SetValue(2);
- Console.WriteLine("Last line in function2().");
- }
- }
And finally the following is the output of this program.

A couple of interesting observations:
- The second line of output is the call to the static constructor (see “This is static Ctor”). But if you refer to the Main() function, we are neither creating the object nor instantiating it. Even SampleClassis not declared as static. Yet, the program makes a static constructor call. Remember in Point 4, we discussed that a static constructor is called well before the instance constructor. The word “well before” is important since it suggests that as soon as static elements are accessed (with or without object creation), the constructor will initialize and then the static objects will be in scope but not as soon as the program begins executing. Because the first line in the output (in other words “First line in Main().”) is the Main() function Console.writeline() statement and then the constructor ofSampleClass is called. To conclude, static elements are in scope as soon as they are referred to by the program in any way.
- Also, there are the objects ObjS2 and ObjS3 created in function1() and function2() respectively. Ideally their scope is within the respective function body only. But when we print the value of the_iCount in Main(), the printed value “2” is set by function2() (in other words objS3.SetValue(2)).
So the take-a-way from the last point is that a static element remains active until the last line of the program is executed. Our assumption is absolutely right with respect to this program. The reason being, the scope of our program is limited to one AppDomain. However if we introduce a different AppDomain, things will change. Let's see another example.
Assume we have one class library project.
- namespace RemoteClassLibrary
- {
- public class RemoteClass
- {
- static int _myID = 0;
-
- public RemoteClass()
- {
- Console.WriteLine("My ID is {0}", ++_myID);
- }
- }
- }
And we have saved the class library DLL to the local drive c:\app\. We have also created another program that uses reflection to execute this code.
- using System.Reflection;
-
- namespace TestingProgram
- {
- class Program
- {
- static void Main()
- {
- const string ClassLibraryPath = @"c:\app\RemoteClassLibrary.dll";
-
-
- Assembly Assembly1 = Assembly.LoadFrom(ClassLibraryPath);
- Assembly1.CreateInstance("RemoteClassLibrary.RemoteClass");
-
-
- Assembly Assembly2 = Assembly.LoadFrom(ClassLibraryPath);
- Assembly2.CreateInstance("RemoteClassLibrary.RemoteClass");
-
- Console.ReadKey();
- }
- }
- }
And the obvious output of this program is:
Please note that even though that assembly is loaded, static members still persist the value, or you can say only a single copy of the static class is created.Now let's modify the main program to introduce multiple AppDomains that will load this assembly separately.
- class Program
- {
- static void Main()
- {
- const string ClassLibrary = "RemoteClassLibrary.RemoteClass";
- const string ClassLibraryPath = @"c:\app\RemoteClassLibrary.dll";
-
-
- AppDomain AppDomain1 = AppDomain.CreateDomain("AppDomain1");
- AppDomain1.CreateInstanceFrom(ClassLibraryPath, ClassLibrary);
-
-
- AppDomain AppDomain2 = AppDomain.CreateDomain("AppDomain2");
- AppDomain2.CreateInstanceFrom(ClassLibraryPath, ClassLibrary);
-
- Console.ReadKey();
- }
- }
Surprisingly the output:
And so even though a single program is executing, the different AppDomain is causing the program to maintain 2 copies of the static member per AppDomain. In short, their scope is limited to the AppDomain.On final note, we explained that the static elements are in scope as soon as they are accessed first and limited to a specific AppDomain.