(C# 9.0 "init" setter) Six Interview Questions and Answers on the init Property Accessor

Following are my top 6 interview questions on the "init" accessor introduced recently in C# 9. The answers have all been fully explained through code examples. All the examples have been kept as short as possible.
(Rev. 18-Jun-2024)

Categories | About |     |  

Parveen,

Here is an article on interview questions and answers on the init only setters in C# 9.

You will need to use an upgraded C# compiler for C# 9.0. Otherwise, the programs given here will not compile.

Ques 1: What is the purpose of init when get-only and readonly already exist?

The following explains the issues with the readonly and get-only setters. Then it explains how the init-only keyword solves them.

Issues with readonly
readonly properties need additional and lengthy code for initialization. This code has to be provided through a constructor - which can be totally avoided by using the init keyword.
Issues with get -only

get only properties need a constructor to initialize them, which can make a class lengthy, and therefore diffcult to read.

using System;

class CMyClass
{

  // get only 
  public int mx { get; }

  // NOT possible to avoid a ctor 
  public CMyClass(int x)
  {

    mx = x;

  }

}

class Program
{

  static void Main(string[] args)
  {

    CMyClass cmc = new CMyClass(5);

  }

}

How init solves these issues?

Now compare the following code with the init keyword. Notice how easier is it to write the class now. And also notice how convenient is it to use object initializer syntax now:

using System;

class CMyClass
{

  // see how simple! 
  // no ctor needed because of "init" 
  public int mx { get; init; }
}

class Program
{

  static void Main(string[] args)
  {

    // it is now possible to use 
    // object initializer syntax 
    // the initializer syntax is impossible 
    // if "mx" were marked get only 
    CMyClass cmc = new CMyClass() { mx = 7 };

    // collection initialization 
    // is easier, too 
    CMyClass[] arr =
    {

      new CMyClass() { mx = 7 },
      new CMyClass() { mx = 4 }
    };

  }

}

Ques 2: What is Construction Phase?

All the following are together called the Construction Phase:

Situation 1: Constructor of a type
The constructor function of a class, struct is referred as the Construction Phase.
Situation 2: Constructor calls through this, base
In the following code we have two examples of the construction phase clearly marked as Examples 1 and 2:
using System;

class CBase
{

  // any property 
  protected int mZ { get; init; }
  // any member 
  int mX;

  // a parametric ctor 
  public CBase(int x)
  {

    mX = x;

  }

}

class CMyClass : CBase
{

  // Example 1: CONSTRUCTION PHASE 
  // this(0) calls its own ctor 
  public CMyClass() : this(0)
  {

  }

  // Example 2: CONSTRUCTION PHASE 
  // base() calls its parent ctor 
  public CMyClass(int x) : base(x)
  {

  }

}

Situation 3: Object Initializer
We are in the construction phase when the object initializer code is running.
Situation 4: Inside a with expression
The following program defines a record using the positional syntax. Then it creates a copy by altering the property x just in time. For details on positional syntax please refer my article (C# 9.0) Record types vs class vs struct type, positional records and non-destructive mutation. The construction phase is marked below.
using System;

// record defined with 
// positional syntax 
// yes! it is a one-liner 
public record RMyRecord(int x);

class Program
{

  static void Main(string[] args)
  {

    // create a record 
    RMyRecord rec1 = new RMyRecord(9);

    // create a mutation using "with" 
    // we are inside CONSTRUCTION PHASE here 
    RMyRecord rec2 = rec1 with { x = 10 };

    Console.WriteLine(rec1.ToString());

    Console.WriteLine(rec2.ToString());

  }

}

Situation 5: Inside an init
We are in contruction phase when an init accessor code is running. The init code could be running inside the derived class also, and could even be running in the base class also - effectively - everywhere.
class CMyClass
{

  // backing store 
  int _mZ;

  public int mZ
  {

    get
    {

      return _mZ;

    }

    init
    {

      // we are inside Construction Phase 
      _mZ = Math.Min(0, value);

    }

  }

}

Situation 6: Inside an Attribute
The following code shows the Attribute class being used to set a property called Name. This, too, is an example of the construction phase.
// inside CONSTRUCTION PHASE 
[MyAttribute(Name = "Hoven")]
class CMyClass
{

}

Ques 3: What is the Importance of Construction Phase?

init accessors can be set [i.e., executed] ONLY during a Construction Phase. After that they become get only.

Ques 4: Explain how init-only setters can be used to set base class properties?

As you can see in the code below, if the property X were marked as get only, then a constructor would have been required. But if we use the init keyword, then a constructor is not required, and the property X can be quickly set just-in-time of a derived class object, by using the object initializer syntax.

class CBase
{

  // X would be in-accessible in derived 
  // classes if the property X were marked 
  // as public int X {get;} 
  // we would have been forced to 
  // add a ctor here 
  public int X { get; init; }
}

class CDerived : CBase
{

}

class Program
{

  static void Main(string[] args)
  {

    // base class X being set 
    CDerived cd = new CDerived() { X = 20 };

    // better yet in C#9 
    // CDerived cd = new() { X = 20 }; 

  }

}

Ques 5: Compare the capabilities of init and set?

An init setter can call other init accessors and set the otherwise-allowed readonly properties, but a set cannot call other init accessors, and neither can initialize any readonly properties. The reason for this is that you are in the construction phase when inside an init block, but you are NOT in the construction phase when inside a set block.

Ques 6: Can a property be marked both as init and readonly?

No.


This Blog Post/Article "(C# 9.0 "init" setter) Six Interview Questions and Answers on the init Property Accessor" by Parveen is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.