Omitted setter vs private setter?

In C# 6, get; only properties are only settable from the constructor. From everywhere else, it is read-only.

A property with a private set; can be set from everywhere inside that class.


From outside the class, it won't change anything if you use this syntax:

public string Foo { get; }

But you won't be able to update Foo within the class, except in the constructor, to do so, you'll need the private setter:

public string Foo { get; private set; }

The difference is that the generated code will produce a readonly field in the second case, and obviously the property won't have a setter.

Let's do a real example:

public class Test
{
    public Test(string name) { Name = name; }
    public string Name { get; private set; }
}

The compiler will compile this like this:

public class Test
{
    private string <Name>k__BackingField;
    public Test(string name)
    {
        <Name>k__BackingField = name;
    }
    public string Name
    {
        get { return <Name>k__BackingField; }
        private set { <Name>k__BackingField = value; }
    }
}

As you can see the compiler has automagically rewritten your code to have a backing field for the property. The field name will be that cryptic name, which is legal .NET but not C# which means you can never write C# code that will conflict with such an automatically generated member.

Basically, automatic properties in C# is just syntactic sugar for a property with a backing field, the actual property being compiled still have a backing field, you just don't have to write it explicitly.

As you can see it also automatically rewrote the constructor to write directly to the field. Note that this will be done everywhere inside this class where the property is written to, since there is no chance for any custom code to be inbetween anyway.

Now let's remove the setter from the property and see what happens:

public class Test
{
    private readonly string <Name>k__BackingField;
    public Test(string name)
    {
        <Name>k__BackingField = name;
    }
    public string Name
    {
        get { return <Name>k__BackingField; }
    }
}

Notice that the field is now readonly, and again, obviously the setter has gone from the property as well.

So this is actually the best way now to create simple types with true readonly properties, not only is the property itself not writable, but the backing field is also readonly meaning you're now better equipped to easily write immutable types.


The private setter is - well - a private set method you can use from inside your class only.

The omitted setter makes the property readonly. So you can only set the value of this property in your constructor(s) or via a static initialization.


A property with an omitted setter is read only everywhere except the class constructor - including inside the class.

A property with a private setter is read only externally (even to subclasses), but writeable internally.