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)를 사용하여 속성을 초기화할 수 있게 해 준다.
일반적으로 속성을 초기화하는 방법으로
(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"
};
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);
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);