Home Full Site
C# 9.0: init only 속성

C# 9 에서 init 이라는 키워드가 새로 추가되었는데, init은 객체의 속성을 처음 초기화하는 용도로 사용된다. init 키워드는 해당 속성이 초기에 한번 설정되면, 그 이후에 변경할 수 없는 기능을 제공하여 Immutable(불변) 속성을 만드는데 사용된다.

일반적으로 속성을 초기화하는 방법으로
(a) 아래 예제(1)처럼 get 만 사용할 수 있는데, 이 방식은 생성자에서 해당 속성을 초기화해야 하며 객체 초기자(Object Initializer)를 사용할 수 없다. 이는 불변 속성을 만들 수 있게 하지만, 속성이 많은 경우 생성자에 모든 파라미터를 받아들여 속성에 할당해야 하는 단점이 있다.
(b) 두번째 방식으로 아래 예제(2)에서처럼 private set을 쓸 수 있는데, 이 방식은 한번 초기화한 속성을 나중에 다른 멤버에서 변경할 수 있어 불변 속성을 만들지는 못한다.
(3) 새로 추가된 init 키워드는 private set과 달리 객체 초기화시 한번 설정되면 다른 값으로 변경할 수 없으며 (즉, 불변 속성을 만들며), 객체 초기자(Object Initializer)를 사용하여 속성을 초기화할 수 있게 해 준다.


예제

// 예제(1) get only
public class Person
{
    public Guid Id { get; }
    public string Name { get; }
        
    public Person(string name)
    {
        this.Name = name;
        this.Id = Guid.NewGuid();
    }
}

Person p = new Person("Tom");

// 예제(2) private set
public class Person
{
    public Guid Id { get; private set; }
    public string Name { get; set; }
        
    public Person()
    {
        this.Id = Guid.NewGuid();
    }

    // 다른 메서드에서 Id 변경 가능
    public void ChangeId()
    {
        this.Id = Guid.NewGuid();
    }
}

// 예제(3) init 속성
public class Person
{
    public Guid Id { get; init; }
    public string Name { get; set; }
        
    public Person()
    {
    }

    public Person(string name)
    {
        this.Name = name;
        this.Id = Guid.NewGuid();
    }

    public void ChangeId()
    {
        // Id 변경 불가
        // this.Id = Guid.NewGuid();
    }
}

// 생성자
Person p1 = new Person("Tom");
// 객체 초기자
Person p2 = new Person
{
    Id = Guid.NewGuid(),
    Name = "Tom"
};



C# 9.0: 필드를 엑세스하는 init accessor

init은 객체 데이타를 처음 초기화할 때만 사용할 수 있는데, 자동 속성뿐만 아니라 물론 필드를 엑세스하는 속성에서도 마찬가지로 init accessor를 사용할 수 있다. 이때 필드는 객체를 초기화할 때 한번만 변경되므로 흔히 readonly 필드를 사용하지만, 읽기전용이 아닌 필드도 init에서 사용할 수 있다. 아래 예제에서 category 필드는 읽기 전용이고 val 필드는 읽기 쓰기가 가능한데, init accessor에서 이들 필드들을 함께 초기화하고 있다. init 속성의 초기화는 생성자가 없는 경우, 아래 예제에서처럼 객체 초기자에서 할 수 있다.

예제

// 예제(4) init accessor
public class Score
{
    private readonly int category;
    private int val;

    public int Value
    {
        get
        {
            return this.val;
        }
        init
        {
            this.category = 1;
            this.val = value;
        }
    }
}

// 객체 초기자를 사용하여 init값 할당
var s = new Score()
{
    Value = 90
};

Console.WriteLine(s.Value);



© csharpstudy.com