Properties

Properties

The Crash Course

  • Properties provide a quick and effective approach to creating getters and setters for instance variables.
  • You can create a property with code like the following:
public int Score
{
    get
    {
        return score;
    }
    set
    {
        score = value;
        if (score < 0)
        {
            score = 0;
        }
    }
}
  • Not all properties need both a setter and a getter.
  • Getters and setters can have different access modifiers.
  • Auto-implemented properties can be created that allow you to quickly define a simple property with default behavior (public int Score { get; set; }).

Introduction

Remember in the previous tutorial, how I talked about how it is common to have lots of times that you want to "get" the value of an instance variable, or "set" the value of that variable, and as a result, you may be making lots of GetSomething() and SetSomething() methods?

C# has a very powerful feature that makes it easy to create a way for other programmers to get or set the value of an instance variable, called properties.

This tutorial will discuss why properties are so helpful, and how to create them in several different ways. It also discusses how when you create an instance of an object, that you can set a bunch of properties all at once, right at the beginning.

The Motivation for Properties

So imagine you are creating a simple class that looks like this, so far:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace Properties
{
    class Player
    {
        private int score;
    }
}

Let's say that you want to be able to have something outside of the class be able to set the value of score, and also be able to get the current value of the score.

The "classic" way (and if you're coming from a Java background, the only way) is to create a method that returns the value of score and another one that sets the value of score, possibly with some extra logic to check to make sure that the score is valid (like non-negative).

This would be done like this:

public int GetScore()
{
    return score;
}
 
public void SetScore(int score)
{
    this.score = score;
    if(this.score < 0)
    {
        this.score = 0;
    }
}

The need for this is extremely common. However, it is a little frustrating to always have to type SetScore(10); It is tempting to just make score public instead of private. Then you could simply say score = 10;. That would be very convenient, except for one problem: now the instance variable is public, and anyone can mess it up (like assign a negative value, or something).

C# has a feature that solves all of these issues: properties. Let's see how to create a property.

Creating Properties

A property is simply an easy way to create these get and set methods that is very readable.

Instead of the two methods that we showed in the previous code snippet, we could instead do this:

public int Score
{
    get
    {
        return score;
    }
    set
    {
        score = value;
        if (score < 0)
        {
            score = 0;
        }
    }
}

This creates a Score property. We can see that it is public, so anyone can use it (though we could also use private if we had wanted). We also specify the type of the property, which in this case is an int. Then we give it a name.

We then use the get and set keyword to show what should happen when someone tries to read the value of the property or set the value of the property. The code inside of the curly braces is essentially the exact same code that was in the GetScore() and SetScore(int) methods, with only one difference.

With a normal method (like SetScore), we can pass in a value to set for the variable. In a property, we use the value keyword instead. This takes on the value of what the person calling the property is trying to set.

So now we can call our property using something like this:

Player player = new Player();
int currentScore = player.Score;
player.Score = 50;

When we try to read from the Score property, the code inside of the get block of the property gets executed and returned. When we try to assign a value to the Score property, the code inside of the set property gets executed. And in this case, the value 50 gets put into the value keyword inside of the set block.

Properties easily allow us to make mechanisms for getting and setting variables, including doing extra work of validating what the user is trying to set, without making our code more difficult to read.

It is worth mentioning that properties are essentially just "syntactic sugar". Behind the scenes, the C# compiler is turning these into methods that do the same stuff.

One other thing that we should discuss here, just to make things clear, is that a property does not necessarily need to belong to an instance variable. In the code we've done with properties so far, this has been the case. But it doesn't have to be that way. Let's look at another example where this isn't the case:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace Properties
{
    class Time
    {
        private int seconds;
 
        public int Seconds
        {
            get
            {
                return seconds;
            }
            set
            {
                seconds = value;
            }
        }
 
        public int Minutes
        {
            get
            {
                return seconds / 60;
            }
        }
    }
}

You can see here that we have a seconds instance variable, along with a Seconds property that lines up with it. (By the way, using lower case names for instance variables, and upper case names for the matching property is very common.)

In addition, we also have a Minutes property that doesn't belong to any instance variable. There's no minutes instance variable at all. Instead, we just do some other work—in this case, return the number of seconds divided by 60.

One other thing this shows us is that we do not need to necessarily provide both a set and a get accessor for the property. Either one is optional, though at least one is required. If you only have a "getter", then the property is "read-only", because you can't set it. If you have only a "setter", well, then… that's kind of strange, because you'd only be able to set a value, but never read it. So what good would it do you? (Though there are a few times where this could be meaningful. But it is pretty uncommon.)

Different Accessibility Levels

So far, when we've seen a property, they've all been public, meaning anyone has access to both the getter (the get block) and the setter (the set block). We also just saw an example where we provided only a getter for the property.

Sometimes, though, we have a property and we want to be able to have the accessibility levels different for the getter and the setter. For instance, allow the getter to be public, but make the setter private.

This is easy to do, because you can specify an access modifier before the get or set keywords, like this:

public int Score
{
    get  // This is public by default, because the property is marked 'public'
    {
        return score;
    }
    private set // This, however, is now private.
    {
        score = value;
    }
}

So in this example, anybody will be able to use the getter, while you will only have access to the setter from inside of the class that it belongs to.

Auto-Implemented Properties

You will probably find yourself making a lot of things that look something like this:

private int score;
 
public int Score
{
    get
    {
         return score;
    }
    set
    {
        score = value;
    }
}

A new feature in C# 3.0 was the ability to create auto-implemented properties that do the exact same thing. Instead of any of the code above (including the private instance variable score), you could simply say:

public int Score { get; set; }

This makes a default instance variable behind the scenes, and simple get and set code. Of course, though, you won't have access to the private instance variable in this situation, though, because it doesn't exist. But it is a nice shorthand way to create a property.

Setting Properties when Creating an Object

There's one other interesting thing that we should discuss when we talk about properties. Let's say you have a Player class like in the previous tutorial that has instance variables for the player's name, score, and number of lives left. Let's also say that you create properties for each of those, called Name, Score, and LivesLeft.

When you create a new Player object, you can use the following syntax to assign values to the Properties, right when you create the object, like this:

Player player = new Player("Frankenstein") { Score = 100, LivesLeft = 7 };

This prevents us from needing to do this:

Player player = new Player("Frankenstein");
player.Score = 100;
player.LivesLeft = 7;

Instead, we can combine it all into one line.

What's Next?

That covers all of the important things about properties.

The next thing we want to go over is something very similar in appearance (but actually quite different in implementation) to a class: a struct.