(C# Language) Properties Auto-Implemented, Init, Readonly, Required

The concept of a property is the most widely used in dotnet programming. Properties provide setter and getter functions for validation of data before it enters or leaves your object. A property has a specific syntax that needs to be mastered.
(Rev. 19-Mar-2024)

Categories | About |     |  

Parveen,

Table of Contents (top down ↓)

Example of a Property

Consider this program. I have attached it as a download to this video. Let me explain it line by line.

First we have a data member that stores the amount. This member is private so it is not directly accessible from outside. This member stores the actual data but it is not accessible from outside the class.

After this we have a property called Amount. This property is public. Take note of the syntax - braces contain the getter and setter functions. The get accessor provides access to the backing member of this property. We have an opportunity of modifying the data before making it available to the caller. In this code we have returned the actual value.

The set method receives data in the value keyword. The incoming data is therefore contained in the value keyword.

The set method makes a validity check. If the validation fails, then it throws an exception. Thus, the setter ensures that invalid data doesn't enter an object.


class Program
{
  // backing member for the property 
  private int _amount;

  // property  
  public int Amount
  {
    get { return _amount; }

    set
    {
      if( (value < 0) || value > 1000)
      {
        throw new ArgumentOutOfRangeException("value");
      }

      _amount = value;
    }
  }

  static void Main()
  {
    Program p = new Program();

    // set 
    p.Amount = 20;

    // get 
    Console.WriteLine($"Amount = {p.Amount}");
  }

}

This code can be made better.

Notice that it contains a magic figure of 1000. Experts say that such figures should be avoided. They affect the readability of your program.

Notice also that there is a magic string called "value" in the code that throws the exception. This string is the keyword "value" in double quotes.

We can make the following two changes -

  1. Replace 1000 by a const int - const int MAX_AMOUNT = 1000;
  2. Replace the string by using a nameof expression - nameof(value). The nameof expression gives the name of an identifier as a string constant.

With these two changes the code becomes more systematic as you can see here. The constant MAX_AMOUNT gives a readable meaning to the magic figure of 1000. Another advantage is that if the figure has to be changed in future, then the change needs to be made just at one place, and the whole code gets updated wherever this figure is used.


class Program
{
  // a constant to avoid hard-coded 
  // values in the program 
  const int MAX_AMOUNT = 1000;

  // backing member for the property 
  private int _amount;

  // property  
  public int Amount
  {
    get { return _amount; }

    set
    {
      if( (value < 0) || value > MAX_AMOUNT)
      {
        throw new ArgumentOutOfRangeException(nameof(value));
      }

      _amount = value;
    }
  }

  static void Main()
  {
    Program p = new Program();

    // set 
    p.Amount = 20;

    // get 
    Console.WriteLine($"Amount = {p.Amount}");
  }

}

Video Explanation (see it happen!)

Please watch the following youtube video:

Auto Implemented Property Syntax

If the getter and setter make no validation, then there is no need to specifically add a backing member.

In this code there is no backing member for the Amount property. Observe also that we only mentioned the keywords get and set. The compiler generated everything else for us.

Notice also that it is possible to mark public, private, etc., accessibilty on a setter or getter as per requirements.


class Program
{
  // property one liner auto implemented 
  public int Amount { get; private set; }

  static void Main()
  {
    Program p = new Program() { Amount = 20 };

    // get 
    Console.WriteLine($"Amount = {p.Amount}");
  }
}

A more Comprehensive Example and Initialization of Objects

Let's look at an example which demonstrates various types of properties.

The first property is an auto-implemented property that has been initialized at declaration.

The second property, Item, is a read only property because no setter has been given. A readonly property can be initialized either at declaration or in a constructor.

After that we have an init only property called ISBN. This property can be intialized once only. It can be initialized at any time - such as at declaration, during constructor, and even after the object has been created. The only restriction is that it can be initialized atmost once.

Lastly, we have the main function. Properties ISBN and Name have been initialized using a special syntax of curly braces. The two properties have been separated by a comma.


class Program
{
  public string Name { get; set; } = String.Empty;

  // readonly must be init at declaration 
  // or in a constructor, but NOT later 
  public string Item { get; } = "motor";

  // init-only, can be set atmost once 
  // at declaration, constructor, any point later 
  // or never, unless marked required 
  public string ISBN { get; init; }

  static void Main()
  {
    Program p = new Program() { ISBN = "3278", Name = "C# Language" };

    // display 
    Console.WriteLine($"{p.Name}, {p.ISBN}, {p.Item}");

  }

}

Try to solve the attached exercises for a hands-on practice on this syntax.


This Blog Post/Article "(C# Language) Properties Auto-Implemented, Init, Readonly, Required" by Parveen is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.