[c#] 인스턴스 속성 초기화의 발전 과정

C#을 처음부터 계속 사용한 분이라면, VB.NET에서는 되는데 C#에는 없는 With...End 문이 아쉬웠을 것 같습니다.

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

var p1 = Person();
p1.FirstName = "모이";
p1.LastName = "디";

그런데 이제 C#에서도 유사하게 사용할 수 있게 되었죠.

var p1 = Person
{
   FirstName = "모이",
   LastName = "디"
};

여기서 문제가 있습니다. Person의 이 두 속성은 초기화 이후에 변경이 되지 않아야 하는 속성이라고 했을 때, 변경이 가능하다는게 문제입니다.

p1.FirstName = "모야";   // 정상적으로 동작하지만 로직 상 맞지 않는 동작

그래서 init 키워드가 추가되었습니다.

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

이제 초기화만 가능하고 이후 수정은 불가능하게 되었습니다. 그런데 nullable 참조 형식이 활성화 되면 이 두 속성에 경고가 뜨는데요, 이 값이 널이 아니어야 하는데 널일 수 있다는 경고입니다.

이를 해결하려면 어쩔 수 없이 생성자에서 해당 속성을 초기화 해야 합니다.

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

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

그런데 좀 장황합니다. 이것을 해결하기 위해 record가 추가되면서 다음처럼 간단히 쓸 수 있게 되었습니다.

record Person(string FirstName, string LastName);

var p2 = new Person("모이", "디");

그리고 이제 합법적으로 with 식을 통해 새로운 인스턴스를 생성하면서 값을 변경할 수 있게 되었습니다.

var p3 = p2 with { FirstName = "모야" };

정리

첫번째 방법으로도 코드 동작은 문제가 없습니다. 하지만 프로그래머는 사람이므로 코드 가독성과 코딩 실수에 의해 버그가 생기지 않도록 하는 언어차원의 예방책이 필요합니다. 이 글에서는 읽기 전용 속성이 예가 될 수 있는데요, 바뀌지 않아야 할 속성은 바뀌지 않아야 한다는 것을 언어에서 지원을 해줍니다.

6 Likes

오와우…record 이렇게 쓰는 거였군요…엄청나게 좋은 예제 감사드립니다…ㅠ

3 Likes