C#idiomatic C#
initcsharp/language-reference/keywords

Language

The `init` keyword (C# Reference)

The `init` keyword is used to declare a `set` accessor that can only be called during an object's initialization: either by a constructor or as part of an object initializer.

  • page csharp/language-reference/keywords/init
  • updated 01/21/2026

The init keyword defines an accessor method in a property or indexer. An init-only setter assigns a value to the property or the indexer element only during object construction. An init enforces immutability, so that once the object is initialized, it can't be changed. An init accessor enables calling code to use an object initializer to set the initial value. In contrast, an automatically implemented property with only a get accessor must be initialized by calling a constructor. A property with a private set accessor can be modified after construction, but only in the class.


ms.custom: "updateeachrelease"

The C# language reference documents the most recently released version of the C# language. It also contains initial documentation for features in public previews for the upcoming language release.

The documentation identifies any feature first introduced in the last three versions of the language or in current public previews.

The following code demonstrates an init accessor in an automatically implemented property:

sample · csharpdocs/csharp/language-reference/keywords/snippets/InitExample2.cs

csharp
class Person_InitExampleAutoProperty
{
    public int YearOfBirth { get; init; }
}

You might need to implement one of the accessors to provide parameter validation. You can do that validation by using the field keyword, introduced in C# 14. The field keyword accesses the compiler synthesized backing field for that property. The following example shows a property where the init accessor validates the range of the value parameter.

sample · csharpdocs/csharp/language-reference/keywords/snippets/InitExample5.cs

csharp
class Person_InitExampleFieldProperty
{
    public int YearOfBirth
    {
        get;
        init
        {
            field = (value <= DateTime.Now.Year)
                ? value
                : throw new ArgumentOutOfRangeException(nameof(value), "Year of birth can't be in the future");
        }
    }
}

The init accessor can be used as an expression-bodied member. Example:

sample · csharpdocs/csharp/language-reference/keywords/snippets/InitExample3.cs

csharp
class Person_InitExampleExpressionBodied
{
    private int _yearOfBirth;

    public int YearOfBirth
    {
        get => _yearOfBirth;
        init => _yearOfBirth = value;
    }
}

The following example defines both a get and an init accessor for a property named YearOfBirth. It uses a private field named _yearOfBirth to back the property value.

sample · csharpdocs/csharp/language-reference/keywords/snippets/InitExample1.cs

csharp
class Person_InitExample
{
     private int _yearOfBirth;

     public int YearOfBirth
     {
         get { return _yearOfBirth; }
         init { _yearOfBirth = value; }
     }
}

An init accessor doesn't force callers to set the property. Instead, it allows callers to use an object initializer while prohibiting later modification. You can add the required modifier to force callers to set a property. The following example shows an init only property with a nullable value type as its backing field. If a caller doesn't initialize the YearOfBirth property, that property has the default null value:

sample · csharpdocs/csharp/language-reference/keywords/snippets/InitNullablityExample.csSnippet4

csharp
namespace InitExample;

// <Snippet4>
class Person_InitExampleNullability
{
    private int? _yearOfBirth;

    public int? YearOfBirth
    {
        get => _yearOfBirth;
        init => _yearOfBirth = value;
    }
}
// </Snippet4>

// <SnippetNonNullable>
class Person_InitExampleNonNull
{
    private int _yearOfBirth;

    public required int YearOfBirth
    {
        get => _yearOfBirth;
        init => _yearOfBirth = value;
    }
}
// </SnippetNonNullable>

To force callers to set an initial non-null value, add the required modifier, as shown in the following example:

sample · csharpdocs/csharp/language-reference/keywords/snippets/InitNullablityExample.csSnippetNonNullable

csharp
namespace InitExample;

// <Snippet4>
class Person_InitExampleNullability
{
    private int? _yearOfBirth;

    public int? YearOfBirth
    {
        get => _yearOfBirth;
        init => _yearOfBirth = value;
    }
}
// </Snippet4>

// <SnippetNonNullable>
class Person_InitExampleNonNull
{
    private int _yearOfBirth;

    public required int YearOfBirth
    {
        get => _yearOfBirth;
        init => _yearOfBirth = value;
    }
}
// </SnippetNonNullable>

The following example shows the distinction between a private set, read-only, and init property. Both the private set version and the read-only version require callers to use the added constructor to set the name property. The private set version allows a person to change their name after the instance is constructed. The init version doesn't require a constructor. Callers can initialize the properties by using an object initializer:

sample · csharpdocs/csharp/language-reference/keywords/snippets/InitExample4.csSnippetClassDefinitions

csharp

// <SnippetClassDefinitions>
class PersonPrivateSet
{
    public string FirstName { get; private set; }
    public string LastName { get; private set; }
    public PersonPrivateSet(string first, string last) => (FirstName, LastName) = (first, last);

    public void ChangeName(string first, string last) => (FirstName, LastName) = (first, last);
}

class PersonReadOnly
{
    public string FirstName { get; }
    public string LastName { get; }
    public PersonReadOnly(string first, string last) => (FirstName, LastName) = (first, last);
}

class PersonInit
{
    public string FirstName { get; init; }
    public string LastName { get; init; }
}
// </SnippetClassDefinitions>

public class Usage
{
    public static void Examples()
    {
        // <SnippetUsage>
        PersonPrivateSet personPrivateSet = new("Bill", "Gates");
        PersonReadOnly personReadOnly = new("Bill", "Gates");
        PersonInit personInit = new() { FirstName = "Bill", LastName = "Gates" };
        // </SnippetUsage>
    }
}

sample · csharpdocs/csharp/language-reference/keywords/snippets/InitExample4.csSnippetUsage

csharp

// <SnippetClassDefinitions>
class PersonPrivateSet
{
    public string FirstName { get; private set; }
    public string LastName { get; private set; }
    public PersonPrivateSet(string first, string last) => (FirstName, LastName) = (first, last);

    public void ChangeName(string first, string last) => (FirstName, LastName) = (first, last);
}

class PersonReadOnly
{
    public string FirstName { get; }
    public string LastName { get; }
    public PersonReadOnly(string first, string last) => (FirstName, LastName) = (first, last);
}

class PersonInit
{
    public string FirstName { get; init; }
    public string LastName { get; init; }
}
// </SnippetClassDefinitions>

public class Usage
{
    public static void Examples()
    {
        // <SnippetUsage>
        PersonPrivateSet personPrivateSet = new("Bill", "Gates");
        PersonReadOnly personReadOnly = new("Bill", "Gates");
        PersonInit personInit = new() { FirstName = "Bill", LastName = "Gates" };
        // </SnippetUsage>
    }
}

C# language specification

For more information, see the C# Language Specification. The language specification is the definitive source for C# syntax and usage.

See also