The community is working on translating this tutorial into Indonesian, but it seems that no one has started the translation process for this article yet. If you can help us, then please click "More info".
Properties
In the previous article, we discussed fields. They are like global variables for a class, allowing you to access them from all methods. We also briefly discussed the fact that fields CAN be accessed from other classes if they are marked as public, but that this is generally not recommended. For variables/fields that you wish to access from outside your class, you should instead use properties.
When you declare a field as public, you are giving complete access to it from the outside - other classes can do whatever they want with it, without any notice to the declaring class. Properties gives the control back to the declaring class, by specifying whether a field is read or write-only and even allowing the declaring class to check and manipulate the value before returning or assigning it to the field.
A property looks a bit like a crossover between a field and a method, because it's declared much like a field with visibility, a data type and a name, but it also has a body, like a method, for controlling the behavior:
public string Name
{
get { return _name; }
set { _name = value; }
}
Notice the special get and set keywords. They are used exclusively for properties, to control the behavior when reading (get'ing) and writing (set'ing) the field. You can have properties with only a get OR a set implementation, to create read-only or write-only properties, and you can even control the visibility of the get or set implementations, e.g. to create a property which can be read from anywhere (public) but only modified from inside the declaring class (private).
You will also notice that I refer to a field called _name. You will have to declare that in your class as well, so that your property can use it. A common usage pattern for fields and properties will look like this:
private string _name = "John Doe";
public string Name
{
get { return _name; }
set { _name = value; }
}
You can now see how the field and the property works together: The get method will return the value of the _name field, while the set method will assign the passed value to the _name field. In the set method, we use the special keyword value which, in this specific situation, will refer to the value passed to the property.
So, this is pretty much as basic as it gets and at this point, we don't do anything that couldn't be accomplished with a simple public field. But at a later point, you may decide that you want to take more control of how other classes can work with the name and since you have implemented this as a property, you are free to modify the implementation without disturbing anyone using your class. For instance, the Name property could be modified to look like this:
private string _name = "John Doe";
public string Name
{
get
{
return _name.ToUpper();
}
set
{
if(!value.Contains(" "))
throw new Exception("Please specify both first and last name!");
_name = value;
}
}
The get method now enforces that the value returned is always in UPPERCASE, no matter which case the backing field (_name) is in. In the set method, we have added a couple of lines of code to check whether the passed value contains a space, because we have decided that the name should always consist of both a first and a last name - if this is not the case, an exception is thrown. This is all very crude and simplified, but it should illustrate the full level of control you get when using properties.
Read-only properties
Most properties you'll see in the examples of this tutorial will be both readable and writeable, because that's the most common usage of properties, but it doesn't always have to be like that. First of all, you can declare a property with only a get-method, like this:
private string _name = "John Doe";
public string Name
{
get { return _name; }
}
In this case, you can no longer change the "Name" property - you can only read it and the compiler will throw an error if you try to assign a value to it. You can still change the value of it from inside the class though, since you can simply assign a new value to the backing field "_name". Doing it that way kind of negates one of the biggest advantage to properties though: The ability to always control whether a value can be accepted. As we already talked about, the set-method is a great way to perform validation of the value, but if you assign a new value to the _name field from multiple places, because the property is read-only, you don't get this validation.
Fortunately for us, C# offers a solution to this: You can define a set method on the property, but limit its visibility, using e.g. the private or the protected keyword. This will give you the best of both worlds, where you can still assign a value to the property from inside the class (or any inherited class if you use the protected keyword) and have it validated accordingly. Here's an example:
private string _name = "John Doe";
public string Name
{
get { return _name; }
private set
{
if(IsValidName(value))
this._name = value;
}
}
public bool IsValidName(string name)
{
return name.EndsWith("Doe");
}
The key difference here is simply the "private" keyword right in front of the "set" keyword, and as mentioned, you can replace it with e.g. protected or internal, depending on your needs.
Auto-implemented properties
In some cases, you don't need all the control over a field and it can feel cumbersome to implement both a field and a property with the get and set methods not doing anything besides what we saw in the first example. You may be tempted to simply declare your variable as a public field to avoid all this extra hassle. But don't do that! Fortunately for all of us, Microsoft decided to add auto-implemented properties in C# version 3, which will save you several lines of code. Just consider the difference:
Regular property with a declared backing field:
private string _name;
public string Name
{
get { return _name; }
set { _name = value; }
}
The exact same behavior, but with an auto-implemented property:
public string Name { get; set; }
Notice that the get and set methods are empty and that no private backing field is declared - in other words, we can now accomplish the exact same behavior as in the first example but with a single line of code! Bear in mind that the private backing field will still exist at runtime - it will be auto-implemented by the compiler, as the name implies. Should you later decide that you need more control of this specific property, you can simply change it to a regular field/property combination with the desired implementation of the get and set methods.
Notice that you are still left with an important mechanism of control from regular properties when using auto-implemented properties: You can leave out the set keyword to create a read-only property, e.g. like this:
public string ReadOnlyProperty { get; }
Write-only properties are not allowed when using auto-implemented properties.
Auto-implemented properties with default values
Prior to C# version 6, you could not define a default value for an auto-implemented property - for that, you would need a declared backing field, which would allow you to initialize the variable with a value:
private string _name = "John Doe";
public string Name
{
get { return _name; }
set { _name = value; }
}
But in C# version 6, Microsoft finally added the ability to initialize an auto-implemented property with a default value, like this:
public string Name { get; set; } = "John Doe";
Expression-bodied properties
Another property-related feature Microsoft implemented in C# 6.0 and 7.0 is the expression bodied members. It simply allows you to write single-line expressions for your properties and methods - in this case, let's look at how to use it for your get/set methods in a way that takes up less space and requires slightly less typing:
private string name;
public string Name
{
get => name;
set => name = value;
}
If your property is read-only, the syntax can be even shorter:
public string Name => "John Doe";
Of course this also works if you need to actually do something before returning the value, like this:
public string Name { get; set; } = "John Doe";
public string FirstName => this.Name.Substring(0, this.Name.IndexOf(" "));
As you can see, this allows you to define a get method but without the actual get and return keywords, while encouraging you to keep it all in one line instead of multiple lines.
Summary
Properties gives your classes more control over how fields can be accessed and manipulated, and they should always be used when you want to give access to fields from outside of the declaring class.