This is your first visit inside The Matrix. Welcome!

The Matrix has you…

This place will take you into the mirage of learning C# programming language, without any previous coding experience being required

Follow the White Rabbit…█

Close
Wednesday, September 20, 2017 16:32

Properties

In today’s lesson, I will talk about one of the previous lesson’s new concepts. The first subject on the list: fields and properties. According to our beloved MSDN, a property is a member that provides a flexible mechanism to read, write, or compute the value of a private field. Properties can be used as if they are public data members, but they are actually special methods called accessors. The only thing that the above definition makes clear so far is that properties are in close relation to fields. So, to get started, lets take the Oven class example from the previous lesson:

class Oven
{
    private string model; // Field "model"
    private string color;
    private int weight;
    private int height;
    private int width;
    private int length;

    public string Model // Property "Model"
    {
        get // Getter of the property "Model"
        {
            return this.model;
        }
        set // Setter of the property "Model"
        {
            this.model = value;
        }
    }

    public string Color
    {
        get { return this.color; }
        set { this.color = value; }
    }

    public int Weight
    {
        get { return this.weight; }
        set { this.weight = value; }
    }

    public int Height
    {
        get { return this.height; }
        set { this.height = value; }
    }

    public int Width
    {
        get { return this.width; }
        set { this.width = value; }
    }

    public int Length
    {
        get { return this.length; }
        set { this.length = value; }
    }
        
    public Oven() // Default constructor
    {
        this.model = "EKK6450AOX";
        this.color = "Gray";
        this.weight = 40;
        this.height = 85;
        this.width = 60;
        this.length = 60;
    }

    public void TurnOn() // Method TurnOn
    {
        Console.WriteLine("Oven turned ON!");
    }

    public void TurnOff()
    {
        Console.WriteLine("Oven turned OFF!");
    }
}

At the top of my example, we have this portion, which we will analyze now:

private string model; //field "model"
private string color;
private int weight;
private int height;
private int width;
private int length;

In yesterday’s article, I said that a class can have Fields. The above lines are the fields of our Oven class, they are variables declared directly in our class, outside of any method, function, etc. There are many uses for fields, but in this particular example, they are used to store the values of the properties private, hidden. For instance, the property Weight is keeping its value private using the field variable weight. We haven’t learned yet about access modifiers, but you probably observed the keyword private in front of each field’s declaration. For now, just know that this makes the field accessible only from within the body of the class declaring that field, and invisible to the entire outside world. By convention, except specific cases, fields should always be private, and their value should be accessible to the outside world only through properties. To better understand this, lets look at the example of two properties:

public string Model //property "Model"
{
    get // Getter of the property "Model"
    {
        return this.model;
    }
    set // Setter of the property "Model"
    {
        this.model = value;
    }
}

public string Color
{
    get { return this.color; }
    set { this.color = value; }
}

First, if you read the lesson Formatting Codes, you should already be able to see that the two properties are synonym, even if they are written differently. The reason why I have written them in two different ways is because if we are writing our properties the way Model property is written, it will occupy a lot of lines, and your program will have a very big length. Compared with the second example of a property, which occupies 5 lines of code, the first one occupies 11. However, as we will see in future examples, properties can have additional lines of codes, in which case it is preferred that we use the first way of writing our properties. This is the reason why you should be aware of both ways of writing a property: whenever your property only gets or sets the value of a field variable, you can just write it in the “shortened” way, to save space.

Now, let’s actually see what these lines mean. First, you can notice that every property has a body contained between { } brackets, just like classes, methods, functions do. This is nothing we haven’t seen and learned already. Inside this body, we have two constructs: get and set.

We can only perform two actions on a property: either read it’s value, or assign a value to it. Get and set (also called accessors) do exactly this: get (also called “getter”) will always give us the stored value of the property, while set (also called “setter”) will always set a value to that property. So, when we write something like this:

int myOvenWeight = Oven.Weight;

the compiler will assign to the myOvenWeight variable the value of the Weight property of the Oven class, by internally using the get portion of the Weight property’s body. Likewise,

Oven.Weight = 40;

is an example of how we are assigning a value to the property Weight of the class Oven, in which case, internally, the compiler will execute the set portion of the property’s body.

Now that we know what get and set are and what they do, lets look a little more carefully at them:

get 
{
    return this.model;
}

You may have already noticed that the get portion of the property, just like the set one, also has its own body, delimited by curly brackets (in fact, you will notice that quite a lot of programming concepts in C# use this concept of body delimited by curly brackets).

Now, inside the body of our get portion of the property, we have

return this.model;

The return keyword is not new, we have already learned about it. It immediately stops the execution inside that body, and returns a value provided to it. The this keyword on the other hand, is completely new to us. As with a lot of lessons on this website, I cannot fully explain it yet, because it relies on concepts I haven’t yet explained. But, on a very short notice, you should know that when we are creating a class – such as our Oven class, we are actually creating a blueprint. Whenever we will actually start using Oven objects, we will not use and modify the blueprint itself, instead we will create copies of our blueprint called instances. This is the same for the real world: an ovens factory will never sell the prototype of an oven itself, it will actually create copies of it, which can be sold. This is why we are using the this keyword to indicate that we are referring not to the blueprint itself, but to the actual copy (instance) of the blueprint that we are using at that particular moment. As an example, if we would create 100 instances of our oven object, and we would have this code:

my37thOven.Model = "Some model here";

then the this keyword inside the set portion of the Model property of our Oven class would refer to that particular copy of our oven object, the 37th copy, NOT the original blueprint. So, whenever we are using this keyword, the compiler understands that we mean the copy we are currently manipulating, not the unique original.

To completely understand the use of the fields, and their role in creating properties, you should know that a property does not mandatory require a field. We could have declared our properties like this:

public int Weight 
{ 
    get; 
    set; 
}

or the shortened version of it, which only occupies one line:

public int Weight { get; set; }

The above way of declaring a property is what programmers called an auto implemented property or automatic property.
Now, suppose we just created our 100 oven object copies, and we want to display their weight on the console:

Console.WriteLine(my37thOven.Weight);

Though some of you would expect the above line of code to generate a compiler error (Use of unassigned variable), because the property doesn’t have a value to return, that is not actually true. Internally, C# will automatically generate a field for our property, which is initialized with the default type value. In our case, the default value for int being 0, the above line of code will display 0 on the console, even if we never assigned the 0 value anywhere in our property. So, this rises the logical question: if C# creates automatic fields for our properties, why should we specifically declare fields anyway? Why not let it be done automatically? There are a few reasons why we need to specify fields explicitly, most of them belonging to rather advanced programming techniques (such as immutability, etc). But for our beginner level of programming, lets consider the following example:

class Employee
{
    public int Age { get; set; }
}

Now, if we create a copy of our Employee class blueprint, we can do this:

myEmployeeCopy.Age = 200;

Have you ever seen an employee of 200 years old age? I haven’t… So, wouldn’t it be great if we could somehow “force” our Age property to only accept a certain range of values? This is where fields come handy:

class Employee
{
    private int _age;

    public int Age 
    {
        get 
        {
            return this._age;
        }
        set
        {
            if (value < 18 || value > 60)
                throw new System.ArgumentException("Age cannot be less than 18 or greater than 60!", "age");
            this._age = value;
        }
    }
}

Now, we have provided additional logic to our property, and you will never see an Employee object with an age of -5. This would have not been possible if we would have used auto-implemented properties (yes, I know, we haven’t learned about throwing exceptions yet, just use it as it is for the moment).

In conclusion, use auto-implemented properties where you have to simply store some property that does not require any additional logic, and fully qualified properties when such thing is required.

Speaking of setters, they have lower priority than returning a literal in the getter. For instance, the following code makes perfect sense:

public int IgnoresSetter
{
    get { return 10; }
    set { /* Meh. Whatever you say, man, I'm still going to return 10 in the getter, you know?.. */ }
}

but the setter of the property is kind of pointless, since the property will always return 10, no matter how much we try to set a new value.

One other important feature of properties is that they can be read only. In a way, you could say that even the above code sample is read-only, since it would return the same value anyway, regardless of us trying to set a different value. But, however, that is not the usual way of declaring a read only property. Instead, we do it like this:

public int MyProperty { get; }

Whenever you would try to set a value to the above property, you will get a compiler error: Property or indexer ‘Oven.MyProperty’ cannot be assigned to — it is read only.

So, what is the use of a property to which we cannot even assign a default value? Yes, we could use a field variable to set a default value, like this:

private int myProperty = 50;

public int MyProperty 
{
    get 
    { 
        return this.myProperty; 
    }
}

but that would defeat the purpose of using auto-implemented properties, wouldn’t it? For this case, we actually have the following solution:

public int MyProperty { get; private set; }

In the above code, we have an auto-implemented property which has a private setter, which means that we can only set its value from within the class declaring the property. Hence, we are allowed to do this:

class Oven
{
    public int MyProperty { get; private set; }

    private void MyMethod()
    {
        MyProperty = 37;
    }
}

but we are forbidden to do this:

my21stOvenCopy.MyProperty = 37;

This is because a private setter only allows us to set a value to the property from within the body of that class, and not from the outside world. We cannot set a value to that property when we create a copy of our Oven object.

Starting with C# version 5.0, there is also a special notation for read only properties, namely this one:

public int MyProperty => 37;

but I’ve rarely seen it used. However, if you like it, go ahead, no one stops you.

Of course, we also have write-only properties, but they are used extremely rarely. Can you even think of an example where you only need to set some data, but never read it?

Comments

comments

Tags: , ,

Leave a Reply