Static members
In the margin of the blueprint the architect keeps a tally: how many houses have already been built from it. This number belongs to no single house. The red house has no "two built" of its own, and neither does the blue one. There is one such number for the whole blueprint, and after each new house it goes up by one.
So far each object had its own fields and properties: its own color, its own floors. But sometimes data is needed once for the whole class. That is what the word static is for:
var a = new House("red");
var b = new House("blue");
Console.WriteLine(House.Count); // 2
class House
{
public static int Count { get; private set; }
public string Color { get; }
public House(string color)
{
Color = color;
Count++;
}
}Let's go through the program:
public static int Count { get; private set; }is a static property: there is oneCountfor the whole classHouse, not one in each house.public string Color { get; }is an ordinary property: each house has its own color.- Every constructor call runs
Count++and raises the very same counter. House.Countis read through the class name, not through a house, and the line prints2.
A static member is a member that belongs to the class itself, not to its objects. Ordinary members, like Color, are each object's own.
Through the class name
A static member exists even when there are no objects at all: before the first new, House.Count is 0. That is why it is used through the class name. The line a.Count does not compile: error CS0176, the compiler asks for the type name.
A const constant also belongs to the type, not to an object. That is why you write int.MaxValue: this constant is one for all int numbers.
Here the blueprint and the class differ. A built house cannot add anything to the blueprint, but an object can change a static member of its class. That is exactly how the constructor of each new house raises Count.
Static methods
A method can be static too. Such a method is not tied to any object, so it is called through the class name:
Console.WriteLine(House.Height(5)); // 15
class House
{
public static int Height(int floors) => floors * 3;
}To find the height of a five-floor house at three meters per floor, no house has to be built: the number of floors is enough. That is why Height is a static method.
You have been using static methods since the first program of the course:
Console.WriteLine: nobody creates aConsoleobject;int.Parseandint.TryParse: they are called through the type nameint;Array.Sort: it is called through the class nameArray, and the array is passed as an argument.
And static void Main() from the theme on the first program is static for the same reason: the runtime calls Main without creating an object of the class Program.
Static or ordinary
Interviewers often ask: "How does a static member differ from an ordinary one?" The answer has three parts:
- a static member is one for the whole class, while each object has its own ordinary members;
- a static member is used through the class name, an ordinary one through an object;
- a static method cannot use ordinary members directly: it has no
this, no object of its own.
A member is made static when it needs no data of a particular object: a shared counter, a calculation from its parameters alone.
Common mistake
A static method reads an ordinary property:
var a = new House("red");
Console.WriteLine(House.Describe());
class House
{
public string Color { get; }
public House(string color) => Color = color;
public static string Describe() => "Color: " + Color; // ✗
}error CS0120: An object reference is required for the non-static field, method, or property 'House.Color'The program does not compile. A static method is called through the class, without a house, so it is unclear whose color it should read. The message says exactly that: to use the ordinary member House.Color, a reference to an object is needed. Remove static and call the method through a house: a.Describe() instead of House.Describe(). Then it reads the color of the house it was called on.
Key points
- A static member, declared with the word
static, is one for the whole class; ordinary members are each object's own. - A static member is used through the class name:
House.Count,int.Parse; through an object it does not compile. - A static method works without an object, so it cannot use ordinary fields and properties directly.
Console.WriteLine,int.Parseandstatic void Main()are static methods.