Declaring methods inside classes is great but what do you do when you want a method you can call anytime? If you’re using C++, then just write a method. But if you still want your method in a class or if you’re using C# where all methods need to be in classes, then you’ll need to make your method static. And you can declare static data too. What does that do?
This episode describes a class called string with a static method called isNullOrEmpty which takes a single parameter of type string and returns true if the passed string is null or if it’s empty. If the passed string is valid and has characters, then this method returns false.
If you have some code outside of the string class and declare a string variable like this:
string * name = someMethodThatMightReturnAString();
// Do something else because we don’t have a string.
String name = SomeMethodThatMightReturnAString();
// Do something else because we don’t have a string.
Notice how there are slight differences between the two examples due to pointers vs. references and due to normal naming differences between C++ and C#. C++ also uses two colons between the class name and the static method while C# uses a dot.
Listen to the full episode or you can read the full transcript below for more about static methods.
When you declare a class method to be static, it stops being associated with a specific instance of the class and behaves more like a standalone method. It’s still a member of the class though and has access to protected and private members. To call a static class method from some code that’s not already part of the class, just scope the method to the class by putting the class name before the method name.
A method that’s not static is called an instance method because you need to create an instance of your class first before you can call the method. You cannot call an instance method by just scoping the method to the class name. Instance methods must be called through the instance variable you created.
Let’s take an example of a string class. Strings can have text stored in them or can sometimes be empty. In C#, the string class is a reference type which means your string variable can also be null. A null string is different than an empty string. Null means you have no string at all. Empty means you have a string but it just has no text. If you want to find out how long your string is, or in other words, how many characters are in your string, you can call the instance method Length. The reason Length is an instance method is because it doesn’t make any sense at all to ask how long are all strings. You can only ask how long is a particular string. The string “cat” is three characters long. An empty string is zero characters.
But what if your string is null? If you try to call the Length method on a null string, you’re going to get a NullReferenceException. That’s a bad thing. And your program will probably crash.
Let’s say you don’t really care if a particular string is null or empty. You just want to make sure that there is some text inside the string. Well, you can’t just call the Length method or any instance method because if you happen to have a null string, then it’ll crash. So you could instead test for null first and if your string is not null, then check the length. That’s a lot of extra code especially when there’s a better way. What you need is a method, and let’s call this method, IsNullOrEmpty, that effectively does what I just described. The method will require a single parameter which is the string you want to test and it will first make sure the string is not null before then calling Length.
Then you need to ask yourself, where should such a useful method exist? It can’t be an instance method in the string class because if you have a null string, then you can’t call it. And if it was an instance method, then it wouldn’t need you to pass the string you want to test, it would just test itself. That’s not what we want. But by making the method static, then it’s always available and can be a member of the string class where it fits nicely.
Because static methods have no association with any specific instance, the IsNullOrEmpty method will work just fine when we have no instance at all.
So if you have some string variable that you’re not sure if it has any text or not or even if you have a string instance at all, then you can now call String.IsNullOrEmpty and pass your variable to test. You’re able to call the IsNullOrEmpty method by putting the String class name in front of the static method name.
What if the string class has another method, an instance method this time, that compares a particular instance with some other instance of the string class. You’re guaranteed that the first string being compared is not null. Because, if it was null, then you wouldn’t be able to call an instance method in the first place. But that other string might be null. And it might be empty. This seems like we could make use of the IsNullOrEmpty method here too. This time, the code is already inside a string method and can call the IsNullOrEmpty method directly without needing to scope the method call to the String class. It’s already in scope.
You can also declare class data members to either be static or not. A static data member exists once in your program no matter how many instances of the class you create. You can use this to make data part of your class but outside of any instances. Because the data is not tied to a particular instance, static methods can work with static data.
In episode 23, I described how a static method can be called to create an instance of a class. The example described the Singleton pattern. Any outside code that wants to create an instance of a singleton class must go through the static method because all the constructors of the class are private. So without having an instance of the class, the outside code can still call the static method which does have access to the constructors and can construct an instance to return to the caller.
But in that episode, I left out one important aspect of the Singleton pattern because I wanted to explain static methods and static data in more detail first. You see, the Singleton pattern has a good reason to make callers go through the static method to get an instance. This is because the static method will always return the same instance. In fact, the method is usually called Instance. The way it works is like this. You already know about the private constructors and the static method called instance that can call the constructor. But the class also has a static data member which is a pointer to the class. Or if this is C#, then it would be a reference to the class. Either way, this static data member starts out being null which means it does not point or refer to any instance. The static method called Instance checks this static data first and creates a new instance only on the first call and assigns the newly created instance to the static data. Then it returns the newly created instance. When the Instance method is called a second time, or a third, or anytime after that, it finds the instance has already been created and just returns the same one that it already created. It can do this because the static data member exists outside of any instance of the class.
I’ll end this episode with one final thought. Whether a class method or data is static or not is separate from any accessibility levels. This means you can have a static method or data that’s public, private, protected, etc.