Skip to content

Instantly share code, notes, and snippets.

@roy-t
Created February 8, 2018 21:50
Show Gist options
  • Save roy-t/10498583d7d7ca0c1b52af96b702fff8 to your computer and use it in GitHub Desktop.
Save roy-t/10498583d7d7ca0c1b52af96b702fff8 to your computer and use it in GitHub Desktop.
The static keyword in C#

So C# is an object oriented (OO) programming language. I'm assuming you're used to OO languages and might not have worked with procedural or functional programming languages. So I will try to explain everything from an OO point of view.

As you well know in an Object Oriented programming language you have objects. Take the following example:

public class Window
{
	private bool open;

	public bool IsOpen
	{
		get
		{
			return open;
		}
	}

	public void Open()
	{
		open = true;
	}

	public void Close()
	{
		open = false;
	}
}

public class House 
{
	public class House()
	{
		BedRoomWindow = new Window();
		KitchenWindow = new Window();
	}

	public Window BedroomWindow  { get; }
	public Window KitchenWindow  { get; }
}

So here we have a Window class. The Window class takes responsibility (encapsulates) the properties of a Window. In this case if its open or closed.

We also have a House class. A House has multiple Windows. The House doesn't really need to know how a Window really works. The house calls the Window constructor (new Window()) two times to create (instantiate) two Window objects. One for the bedroom, and one for the kitchen. If we call BedroomWindow.Open() the bedroom window will open, the kitchen window will stay closed (KitchenWindow.IsOpen == false). This happens because the field open is not shared between instances. Both the KitchenWindow instance and the BedroomWindow instance have their own piece of memory to store the field open in.

The above you probably already all knew. So let's look at what happens when we introduce the static keyword. Let's change our Window class to this:

public class Window
{
	private static bool open;

	public bool IsOpen
	{
		get
		{
			return open;
		}
	}

	public void Open()
	{
		open = true;
	}

	public void Close()
	{
		open = false;
	}
}

Now let's repeat the same experiment. We create a new House and then we call BedroomWindow.Open(). If we now check the kitchen window we will see that KitchenWindow.IsOpen is also true. This is because the static keyword indicates that the field is not part of any one object. Its part of the class itself. This is why you can reference the field using the this pointer anymore. (Writing this.open in a method in the Window class won't work). But you can reference it using the name of the class (Writing Window.open in a method in the Window class will work).

You can also mark a field with const:

public class Window 
{
	public const double WeightOfGlassPerCubicMeter = 3.0;	
}

A const field is basically a static field of a primitive type (like an integer or bool, not something you can construct) that can't be changed.

You can also use the static keyword on properties, I don't think they need extra explanation as properties are basically fields in disguise :).

You can add static to a method. Let's try that:

public class Window
{
	private bool open;

	public bool IsOpen
	{
		get
		{
			return open;
		}
	}

	public void Open()
	{
		open = true;
	}

	public void Close()
	{
		open = false;
	}

	public static void Print(Window window)
	{
		Console.WriteLine($"The window is {window.IsOpen? "open" : "closed"});
	}
}

So now we have the static method print. We can reference it by using the class name: Window.Print(house.BedRoomWindow). A static method is again part of the class, and not of the object. This is handy, we can use it everywhere without having to instantiate a Window. But since the method is part of the class it doesn't know anything about a specific instance of Window. So we cannot use the this pointer inside static methods. Since the computer would not understand what specific instance this is pointing to.

So that leaves us with two more places where we can use static.

We can create a static class:

public static class Math
{
	public static int Sum(int a, int b)
	{
		return a + b;
	}
}

Marking a class as static forces us to use only static methods, static fields, and static properties in that class. Its impossible to instantiate (call new Math()) a static class. Marking a class as static is a forceful reminder to ourselves that we do not intent to create objects, but that we merely want a convenient grouping of stuff to use everywhere. For example, C#'s built-in Math class is marked static.

Last, but not least, we have static constructors.

public static class ComputerInfo
{
	public static int NumberOfProcessors { get; }

	public static ComputerInfo()
	{
		ComputerInfo.NumberOfProcessors = MagicMethodThatCalculatesNumberOfProcessors();
	}
}

Static constructors are very rarely used. The code in a static constructor is executed the very first time you use ANY field, property, or method, static or non-static, on the class that has the static constructor. A static constructor is usually used to initialize a static field or property. Since you do not call a static constructor yourself, a static constructor cannot have parameters (how would the computer know what to pass in anyway?).

So that's that for the static keyword :). How about some use cases

  • Use static fields or properties for things that are not relevant for a single object, but concern the entire class. For example: in a Math class use a static (or const) field to store the value of Pi. Think of double.PositiveInfinity

  • Use static methods to perform tasks that are not relevant for a single object. Static methods are great since they themselves do not have the (hidden) state of an object. This makes them very easy to (unit) test. Think of the string.Compare methods. You can also use static methods when you are creating things, but do not want to use a constructor. Think for example about double.Parse which turns a string into a number.

  • Use static class if you want a class with only static methods. This is usually handy for helper libraries. Think of the Path and Math classes in

  • Do not use static constructors, unless you have a really really good reason to use them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment