C# Properties


This entry is part 9 of 11 in the series C# Classes

Properties and fields provide access to data contained in an object. The various pieces of data contained within an object together make up the state of that object.

If your object was CupOfCoffee, you need to provide it with a state for it to have any meaning. Think of the coffee’s possible adjectives: hot, iced, brewed, instant, black, small, large, double-double and so on. Knowing your object requirements and behaviour ahead of code-writing time is important. It will save time in the end. In this example, be sure that you understand the menu of the restaurant before you work on your object’s fields properties and methods.

When it comes time to code, keeping your objects in a valid state is important. Carefully writing your properties helps with this.

A property is often associated with a field. A common practice is to encapsulate a field in a class by declaring the field private and declaring a public property to give controlled access to the field from outside the class. The field associated with a property is called the backing field or backing store.

using System;
namespace PropertiesIllustratedSyntax
{
    class Program
    {
        static void Main(string[] args)
        {
            C1 c = new C1();
            // Read from the property as if it were a field.
            Console.WriteLine("MyValue: {0}", c.MyValue);
            c.MyValue = 20; //Use assignment to set the value of a property.
            Console.WriteLine("MyValue: {0}", c.MyValue);
        }
    }
    class C1
    {
        private int theRealValue = 10; // Backing Field: memory allocated
        public int MyValue // Property: no memory allocated
        {
            set { theRealValue = value; } // Sets the value of field theRealValue
            get { return theRealValue; } // Gets the value of the field
        }
    }
}

Person Class

Let’s go back to our Person class. We will add Properties to our previous example in the post called C# Access Modifiers. Note that we are now using get and set and they are C# keywords so they should be lower case. Also note that we are using value, which is also a C# keyword. We do not have any logic in our Property yet. The set and get accessors can be declared in either order, and no methods other than the two accessors are allowed on a property. All paths through the implementation of a get accessor must include a return statement that returns a value of the property type.

        public class Person
        {
            private DateTime _birthdate;
            public DateTime Birthdate
            {
                get { return _birthdate; }
                set { _birthdate = value; }
            }
        }

Here is a screenshot. Suppose we declared Birthdate to be public. Note that we have access to the Birthdate property because we made it public. We also have a few other methods that come along with our objects.

Auto-Implemented Properties

We can write even less code for our get and set. When the C# compiler sees this code below, it creates a private field for us. You can check out the code that the compiler created by using ILDASM. Mosh discusses this in the video Properties of his Intermediate C# video series at Udemy.com

public DateTime Birthdate { get; set; }

Now we need to set a property that calculates the age based on the birth date. We will create a property with a get method and no set method. We never set the age because it is calculated.

        public class Person
        {
            public DateTime Birthdate { get; set; }
            public int Age
            {   // no set method declared here intentionally
                get
                {
                    var timespan = DateTime.Today - Birthdate;
                    var years = timespan.Days/365;
                    return years;
                }
            }
        }
        static void Main(string[] args)
        {
            var person = new Person();
            person.Birthdate = new DateTime(1974, 7, 18);
            Console.WriteLine(person.Birthdate);
            Console.WriteLine(person.Age);
            Console.ReadKey();
        }

The above code works. What if we never set the birth date in the main program? What is the default value for a DateTime? That is the value that will be set for the Birthdate. The default value is January 1, in year 0001. When calculated, the person’s age will be the same as the current year, which is 2018. The program does not crash when the birth date is not set.

When we use the getters and setters, { get; set; }, the compiler automatically does two things for us:

  • internally creates a private field
  • implements a get and set accessor methods

Set it One Time – Only in the Constructor

Suppose you wanted the Person class to have the birth date set only one time? Once it is set, it cannot be changed. In other words we want a “write once”. How do you do that? There are two steps to accomplish that. First use the private keyword in the setter. Then we create a constructor. As soon as we change the set accessor to private with the private keyword, we are no longer able to set the value in the main program unless we use the constructor, and that happens only one time at instantiation. If we use the code person.Birthdate = new DateTime(1974, 7, 18); we get an error saying that the property or indexer cannot be used in this context because the set accessor in inaccessible.

    class Program
    {
        public class Person
        {
            public string Name { get; set; }  // an auto-implemented property
            public DateTime Birthdate { get; private set; } // an auto-implemented property

            public Person(DateTime birthdate)  // a constructor
            {
                Birthdate = birthdate;  // set the birthdate property
            }

            public int Age  // a calculated property
            {   // no set method declared here intentionally
                get
                {
                    var timespan = DateTime.Today - Birthdate;
                    var years = timespan.Days/365;
                    return years;
                }
            }
        }
        static void Main(string[] args)
        {
            var person = new Person(new DateTime(1974, 7, 18));
            
            Console.WriteLine(person.Birthdate);
            Console.WriteLine(person.Age);
            Console.ReadKey();
        }
    }

Class coding conventions are designed to keep your class code well organized. It is best practice to keep your types of code in order, separated by a vertical space. What is that order?

  1. Auto-implemented Properties
  2. Calculated Properties (such as Age in this example)
  3. Constructors
  4. Properties
  5. Methods

Code Snippet prop

You can save yourself time by using code snippets. For example, you can use prop Tab Tab typethetype Tab typethename Enter to create a property with a get and set. For Console.WriteLine you can use cw Tab Tab.

Series Navigation<< C# FieldsC# Property Example >>