Home > Mobile >  private init in C# props?
private init in C# props?

Time:01-03

What does private access modifier for init only setter in C# mean? I usually make setter as private for most of the properties in my domain classes. With init, does it matter?

The following seem to work without any problem, the compiler does not complain.

public class Point
{
    public int X { get; private init; }
    public int Y { get; private init; }
}

So how is the above different from the below. There is not private below.

public class Point
{
    public int X { get; init; }
    public int Y { get; init; }
}

CodePudding user response:

It affects where the setter can be called from, just like normal setters.

Consider this code:

public class Point
{
    public int X { get; private init; }
    public int Y { get; private init; }
}

class Program
{
    static void Main()
    {
        var point = new Point { X = 10, Y = 20 };
    }
}

That fails with two compile-time errors:

The property or indexer 'Point.X' cannot be used in this context because the set accessor is inaccessible

(and the equivalent for Y).

The same initializer would be valid in the Point class, because the set accessors are accessible there.

Likewise the code above would be valid without the private part of the set accessors, because then they can be called from anywhere (as part of an object initializer).

CodePudding user response:

The init keyword was added in c# 9.0 in order to add immutable properties on objects.

The problem we used to have is that if you have this object you could still modify the Name property (although it has a private setter) via a public method. for example:

public class Person
{
    public Person(string name)
    {
        this.Name = name;
    }

    public void SetName(string name)
    {
        this.Name = name;
    }

    public string Name { get; private set; }
}

And we also couldn't use object initializers

var person = new Person
{
    Name = "Jane Doe" // Compile Error 
};

Now, if we change the code to use init

public class Person
{
    public Person(string name)
    {
        this.Name = name;
    }

    public string Name { get; init; }
}

We are now able to use object initializers

var person = new Person
{
    Name = "Jane Doe" // No error
};

But, if we use your private init like your example

public class Person
{
    public Person(string name)
    {
        this.Name = name;
    }

    public string Name { get; private init; }
}

We won't be able to do use object initializers

var person = new Person
{
    Name = "Jane Doe" // Compile error
};
  • Related