"This" keyword in C#, easier than you think!

brian
Brian Ngamsom
c#, .net, dotnet

One of the confusing topics in programming is, "this" keyword. Unless you are coming from an OOP language background. This concept might be confusing to you. But not anymore, I will show you how easy it is to understand "this".

Why do we need "this"?

A short answer is we don't. Let me explain.

If you look at the code below, can you spot a problem?

Car.cs
public class Car
{
    private string model;
    private int maxSpeed;
    
    public Car(string model)
    {
        model = model;
    }
    
    public void PrintModel() => Console.WriteLine($"Car Name: {model}");
    public void PrintMaxspeed() => Console.WriteLine($"Car Max Speed: {maxSpeed}");
}

This code seems fine at first glance, but there is one problem.

If I try to create an object from this Car class and print out the name of the model. You'd expect it to print "BubbleBee", does it?

Program.cs
Car myCar = new Car("BubbleBee");

myCar.PrintModel();

//Car Name: 

But it prints out "" (empty string). Why is that?

Well, it turns out this constructor is the problem. Constructor responsible for assign a value that get pass into the property of the class. But this constructor here has one parameter called "model" which accidentally matches with the name of the property of this class. So, which one is which then?

It turns out that the constructor is not smart enough to distinguish between those two.

Car.cs
    public Car(string model)
    {
        model = model;
    }
    

"this" comes to the rescue.

There are a few solutions to this problem that we see above. The first solution is to use "this" keyword to distinguish between the scope of the variable.

If you look at the code below, which I have slightly modified. You will notice that I have added the "this" keyword in front of the "model" inside a constructor.

Car.cs
public class Car
{
    private string model;
    private int maxSpeed;
    
    public Car(string model)
    {
        this.model = model;
    }
    
    public void PrintModel() => Console.WriteLine($"Car Name: {model}");
    public void PrintMaxspeed() => Console.WriteLine($"Car Max Speed: {maxSpeed}");
}

What does this mean? It means, "this.model" will now point to "model" which is the property of this class. If I called PrintModel() again.

Program.cs
Car myCar = new Car("BubbleBee");

myCar.PrintModel();

//Car Name: BubbleBee

Now we can see the name of the model that we pass into that constructor.

Say you hate "this", what are the other options?

If you think this is not a good idea, there are a few more solutions to this problem. All of them seem to be a better choice (in my opinion).

Rename the property name

You can rename the property name of the class. This make sure you don't have a duplicate property name that collides with the variable name of the constructor.

Car.cs
public class Car
{
    private string carModel;
    private int maxSpeed;
    
    public Car(string model)
    {
        carModel = model;
    }
    
    public void PrintModel() => Console.WriteLine($"Car Name: {carModel}");
}

You can see from the above code sample, I have update the name of the model to be "carModel". Now they are different from the name of the variable inside a constructor.

Use underscore (the most used pattern)

This is the most popular pattern in the C# code base. As it can retain the meaning of the variable name at the same time make it easy to distinguished.

Car.cs
public class Car
{
    private string _model;
    private int maxSpeed;
    
    public Car(string model)
    {
        _model = model;
    }
    
    public void PrintModel() => Console.WriteLine($"Car Name: {_model}");
}

This approach is cleaner and easier to read. This also prevents developers from coming up with an alternate name that deviates from the real meaning of that variable.

Another useful for "this"

There is another useful use for "this" keyword. You might not see this pattern that often, but it's good to know.

Car.cs
public class Car
{
    private string _model;
    private int _maxSpeed;
    
    public Car(){}
    
    public Car(string model)
    {
        _model = model;
    }
    
    public Car(int maxSpeed) 
    {
        if (maxSpeed > 60)
        {
           _maxSpeed = 60; 
        }
        _maxSpeed = maxSpeed;
    }
    
    public Car(string model, int maxSpeed) 
    {
        _model = model;
        if (maxSpeed > 60)
        {
           _maxSpeed = 60; 
        }
        _maxSpeed = maxSpeed;
    }
    
    public void PrintModel() => Console.WriteLine($"Car Name: {model}");
}

From the code sample above, you will notice that I have a few constructor. This is called constructor overloading. This approach helps you create an object from this class, depends on the number of parameter that you pass into that constructor. For instance, if I want to create an object from this class with just 1 parameter, I can do that. Or if I want to create with 2 parameters, I also can. Now, this seem to be handy, but we have one slight problem here.

If you notice, we have the code that checks for the "maxSpeed" inside our constructor. The issue is that they are duplicating code. This means if I want to change my business logic from "maxSpeed = 60" to "maxSpeed = 70", I will need to change it in 2 places. Does it seem to be a problem, does it? Not quite.

In this example, I have only 3 constructor (excluded an empty constructor). What if I have 10? I need to make a change in all of them. This doesn't seem practical.

The solution is quite simple. Using "this"!

Car.cs
public class Car
{
    private string _model;
    private int _maxSpeed;
    
    public Car(){}
    
    public Car(string model) : this(model, 0){}
    
    public Car(int maxSpeed) : this("", maxSpeed){}
    
    //this is a master constructor
    public Car(string model, int maxSpeed) 
    {
        _model = model;
        if (maxSpeed > 60)
        {
           _maxSpeed = 60; 
        }
        _maxSpeed = maxSpeed;
    }
    
    public void PrintModel() => Console.WriteLine($"Car Name: {_model}");
}

The code above utilised "this" keyword to refer to the master constructor. So now if I want to make a change to my business logic, I have only 1 place to change. How's that!

I still hate "this", can I use another approach?

Yes, you can.

Car.cs
public class Car
{
    private string _model;
    private int _maxSpeed;
    
    public Car(string model = "", int maxSpeed = 0) 
    {
        _model = model;
        if (maxSpeed > 60)
        {
           _maxSpeed = 60; 
        }
        _maxSpeed = maxSpeed;
    }
    
    public void PrintModel() => Console.WriteLine($"Car Name: {_model}");
}

This code here use something called "optional arguments". This reduce the use of multiple constructors by passing in a default value for each parameters.

That's all for "this". I hope you can fully understand it now!

Till next time.