푸터 콘텐츠로 바로가기
.NET 도움말

C# Init Keyword (How It Works For Developers)

The init keyword in C# 9.0 introduced a new way of defining class properties for creating immutable objects. In earlier versions of C#, properties were typically used with get and set accessors to read from and write to object fields. However, with init, you can make writable properties only during object initialization, making them read-only afterward.

This tutorial will explore using the C# init keyword with practical examples and scenarios using the IronPDF library. You'll also learn about the critical differences between traditional property setters (set) and the new init-only setters.

Basic Example of the Init Keyword

Let's start with a basic example:

public class Person
{
    public string FirstName { get; init; }
    public string LastName { get; init; }
}

var person = new Person
{
    FirstName = "Iron",
    LastName = "Dev"
};

// person.FirstName = "Jane";  // This will give a compile-time error.
public class Person
{
    public string FirstName { get; init; }
    public string LastName { get; init; }
}

var person = new Person
{
    FirstName = "Iron",
    LastName = "Dev"
};

// person.FirstName = "Jane";  // This will give a compile-time error.
$vbLabelText   $csharpLabel

C# Init Keyword (How It Works For Developers): Figure 1 - IDE throwing an error due to properties being marked as init-only

In this example, FirstName and LastName are marked as init-only properties. This means they can be assigned only during object initialization. After the object is created, attempting to change the values will cause a compile-time error.

Why Use the Init Keyword?

The main reason for using the init keyword is to make object properties immutable after initialization. Traditionally, you could mark properties as read-only to achieve immutability. However, you would often need a constructor that accepts all necessary values to set the fields, which can lead to constructor boilerplate code. With init, you can achieve the same goal using object initializers without writing long constructors.

public class Person
{
    public string FirstName { get; init; }
    public string LastName { get; init; }
    // Without using constructor boilerplate for property initialization
}

var person = new Person
{
    FirstName = "John",
    LastName = "Doe"
};
public class Person
{
    public string FirstName { get; init; }
    public string LastName { get; init; }
    // Without using constructor boilerplate for property initialization
}

var person = new Person
{
    FirstName = "John",
    LastName = "Doe"
};
$vbLabelText   $csharpLabel

Object Initialization with Init-Only Properties

Using init works seamlessly with object initializers. Instead of relying on constructors to set values, you can define the properties you need directly while creating an object.

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

var point = new Point { X = 10, Y = 20 };

// point.X = 30;  // This will throw a compile-time error
public class Point
{
    public int X { get; init; }
    public int Y { get; init; }
}

var point = new Point { X = 10, Y = 20 };

// point.X = 30;  // This will throw a compile-time error
$vbLabelText   $csharpLabel

This creates a simple, immutable object of type Point. Notice that the values for X and Y are set at initialization and can't be modified later.

Mixing init with Constructors

Although the primary use case for init is object initialization via object initializers, you can still use a constructor if needed. This is particularly useful when enforcing specific property values during object creation.

public class Person
{
    public string FirstName { get; init; }
    public string LastName { get; init; }

    public Person(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }
}
public class Person
{
    public string FirstName { get; init; }
    public string LastName { get; init; }

    public Person(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }
}
$vbLabelText   $csharpLabel

You can use both constructors and init properties together. This approach offers more flexibility while still enforcing immutability after object construction.

Benefits of Init Over Private Set

Previously, developers used a private set accessor to limit property modification outside the class.

public class Person
{
    public string FirstName { get; private set; }
    public string LastName { get; private set; }

    public Person(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }
}
public class Person
{
    public string FirstName { get; private set; }
    public string LastName { get; private set; }

    public Person(string firstName, string lastName)
    {
        FirstName = firstName;
        LastName = lastName;
    }
}
$vbLabelText   $csharpLabel

Although this approach works, it requires constructor boilerplate code to initialize properties. Also, it allows the class itself to modify the properties later, which isn't always ideal for immutable objects. The init keyword removes this issue, as it only allows initialization at object creation time and blocks any modification afterward.

Handling Initialization with Read-Only Fields and Init Accessors

The init keyword can initialize fields or properties during object creation while they remain immutable afterward. While read-only fields provide immutability, the init accessor offers a similar capability for properties. Here's how you can handle immutability in two ways: using read-only fields and init properties.

Using Read-Only Fields with a Constructor

In this example, we use read-only fields for firstName and lastName, which are set during object construction. These fields can only be assigned once in the constructor and cannot be modified afterward:

public class Person
{
    private readonly string firstName;
    private readonly string lastName;

    public string FirstName => firstName;
    public string LastName => lastName;

    public Person(string firstName, string lastName)
    {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}
public class Person
{
    private readonly string firstName;
    private readonly string lastName;

    public string FirstName => firstName;
    public string LastName => lastName;

    public Person(string firstName, string lastName)
    {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}
$vbLabelText   $csharpLabel

Using Init Accessors for Initialization

Alternatively, we can use the init accessor to create read-only properties that can be initialized during object creation but can't be changed afterward. This eliminates the need for read-only fields and provides a more modern syntax:

public class Person
{
    public string FirstName { get; init; }
    public string LastName { get; init; }
}
public class Person
{
    public string FirstName { get; init; }
    public string LastName { get; init; }
}
$vbLabelText   $csharpLabel

Introduction to IronPDF

C# Init Keyword (How It Works For Developers): Figure 2 - IronPDF: The C# PDF Library

IronPDF is a powerful PDF generation and manipulation library designed for C# developers. It simplifies working with PDFs by converting HTML, CSS, images, and other content into PDF documents. With features like pixel-perfect rendering, cross-platform support, and easy integration into .NET projects, IronPDF is ideal for developers needing to create high-quality PDFs quickly. You can use it with .NET Core, Framework, and Standard, and it supports a wide range of platforms, including Windows, Linux, and macOS.

Case: Using IronPDF with C# Init Keyword

To create immutable objects in a C# project while generating PDFs, you can combine the init keyword with IronPDF. The init keyword ensures the object's integrity after it's initialized, while IronPDF processes the data and generates PDFs based on that immutable model.

Make sure IronPDF is correctly referenced in your project. You can install it via NuGet:

Install-Package IronPdf

Here is the code example:

using IronPdf;

public class Person
{
    public int Id { get; init; }
    public string FirstName { get; init; }
    public string LastName { get; init; }
}

public class PDFGenerator
{
    public static void CreatePersonPDF(Person person)
    {
        var htmlContent = $@"
        <html>
        <body>
            <h1>Person Information</h1>
            <p>ID: {person.Id}</p>
            <p>First Name: {person.FirstName}</p>
            <p>Last Name: {person.LastName}</p>
        </body>
        </html>";

        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf(htmlContent);
        pdf.SaveAs($"Person_{person.Id}.pdf");
    }
}

class Program
{
    static void Main(string[] args)
    {
        var person = new Person
        {
            Id = 1,
            FirstName = "Iron",
            LastName = "Dev"
        };

        PDFGenerator.CreatePersonPDF(person);
    }
}
using IronPdf;

public class Person
{
    public int Id { get; init; }
    public string FirstName { get; init; }
    public string LastName { get; init; }
}

public class PDFGenerator
{
    public static void CreatePersonPDF(Person person)
    {
        var htmlContent = $@"
        <html>
        <body>
            <h1>Person Information</h1>
            <p>ID: {person.Id}</p>
            <p>First Name: {person.FirstName}</p>
            <p>Last Name: {person.LastName}</p>
        </body>
        </html>";

        var renderer = new ChromePdfRenderer();
        var pdf = renderer.RenderHtmlAsPdf(htmlContent);
        pdf.SaveAs($"Person_{person.Id}.pdf");
    }
}

class Program
{
    static void Main(string[] args)
    {
        var person = new Person
        {
            Id = 1,
            FirstName = "Iron",
            LastName = "Dev"
        };

        PDFGenerator.CreatePersonPDF(person);
    }
}
$vbLabelText   $csharpLabel

Conclusion

C# Init Keyword (How It Works For Developers): Figure 3 - IronPDF Licensing Page

In summary, the C# init keyword allows you to create immutable objects while offering flexibility during object initialization. It's a cleaner and safer alternative to private set accessors, reducing the need for constructor boilerplate code. Combining the init keyword with read-only fields, structs, and validation logic helps you build robust and secure data structures that preserve immutability without sacrificing readability or flexibility. IronPDF offers a free trial, and licenses start from $799. This gives you access to its full features, including editing, compressing, and securing PDFs.

자주 묻는 질문

C#에서 HTML을 PDF로 변환하려면 어떻게 해야 하나요?

IronPDF의 RenderHtmlAsPdf 메서드를 사용하여 HTML 문자열을 PDF로 변환할 수 있습니다. 또한 RenderHtmlFileAsPdf를 사용하여 HTML 파일을 PDF로 변환할 수도 있습니다.

C#에서 init 키워드의 용도는 무엇인가요?

Init 키워드를 사용하면 객체를 초기화하는 동안에만 설정할 수 있는 속성을 정의하여 이후 불변성을 보장할 수 있습니다. 이 기능은 한 번 생성된 후에는 변경해서는 안 되는 객체를 만들 때 특히 유용합니다.

Init 키워드는 C#에서 객체 불변성을 어떻게 향상하나요?

Init 키워드를 사용하면 객체의 초기화 단계에서만 속성을 설정할 수 있으므로 이후에는 변경할 수 없습니다. 이렇게 하면 개체가 생성된 후에는 변경할 수 없게 됩니다.

PDF 생성을 위해 라이브러리와 함께 init 속성을 사용할 수 있나요?

예, 초기화 속성은 IronPDF와 같은 라이브러리와 함께 사용하여 변경할 수 없는 객체에서 PDF를 생성하여 PDF에 사용되는 데이터가 프로세스 전반에 걸쳐 일관성을 유지하도록 할 수 있습니다.

기존 설정기보다 init 키워드를 사용하면 어떤 이점이 있나요?

기존 설정자 대신 init 키워드를 사용하면 불변성을 높이고, 긴 생성자 코드의 필요성을 줄이며, 초기화 후 객체 속성을 수정할 수 없습니다.

C#에서 PDF 생성과 불변 속성을 통합하려면 어떻게 해야 하나요?

Init 속성을 사용하여 변경 불가능한 개체를 생성하고 이러한 개체를 IronPDF에 전달하면 데이터를 활용하여 일관되고 신뢰할 수 있는 PDF 문서를 생성할 수 있습니다.

최신 C# 애플리케이션을 만들 때 init 키워드는 어떤 역할을 하나요?

Init 키워드는 개발자가 간결한 구문으로 변경 불가능한 객체를 정의하고 코드 안전성을 높이며 버그를 줄일 수 있도록 함으로써 최신 C# 애플리케이션을 만드는 데 중요한 역할을 합니다.

C# 프로젝트에 PDF 생성을 위한 라이브러리를 설치하려면 어떻게 해야 하나요?

다음과 같은 명령으로 NuGet 패키지 관리자를 사용하여 C# 프로젝트에 IronPDF와 같은 라이브러리를 설치할 수 있습니다: Install-Package IronPdf.

애플리케이션 개발에서 불변성이 중요한 이유는 무엇인가요?

불변성은 애플리케이션 전반에서 데이터 무결성과 일관성을 보장하여 유지 관리가 쉬워지고 버그 발생 가능성이 줄어들기 때문에 중요합니다.

Init 키워드의 사용을 설명하는 실제 사례에는 어떤 것이 있나요?

실제적인 예로 init 키워드를 사용하여 초기화 중에만 설정할 수 있는 속성을 가진 클래스를 정의하여 생성된 객체가 변경되지 않도록 하는 것을 들 수 있습니다. 이는 데이터 일관성이 중요한 시나리오에서 특히 유용합니다.

커티스 차우
기술 문서 작성자

커티스 차우는 칼턴 대학교에서 컴퓨터 과학 학사 학위를 취득했으며, Node.js, TypeScript, JavaScript, React를 전문으로 하는 프론트엔드 개발자입니다. 직관적이고 미적으로 뛰어난 사용자 인터페이스를 만드는 데 열정을 가진 그는 최신 프레임워크를 활용하고, 잘 구성되고 시각적으로 매력적인 매뉴얼을 제작하는 것을 즐깁니다.

커티스는 개발 분야 외에도 사물 인터넷(IoT)에 깊은 관심을 가지고 있으며, 하드웨어와 소프트웨어를 통합하는 혁신적인 방법을 연구합니다. 여가 시간에는 게임을 즐기거나 디스코드 봇을 만들면서 기술에 대한 애정과 창의성을 결합합니다.