Microsoft .NET/C#

[C#] record 타입 정리, class와 차이와 with 식

전자기린 2026. 11. 10. 00:42

C# 9에서 추가된 record를 실무에서 쓸 때 필요한 부분만 정리했습니다.

절차

  1. class와의 차이
  2. 값 비교와 with 식
  3. Deconstruct와 패턴 매칭
  4. 주의할 점

 

1. class와의 차이

// 한 줄로 값 객체 정의
public record UserDto(int Id, string Name);

// 위 한 줄이 아래를 자동 생성합니다
public class UserDto
{
    public int Id { get; init; }
    public string Name { get; init; }

    public UserDto(int id, string name) => (Id, Name) = (id, name);

    // 값 기반 Equals, GetHashCode, ToString
}

init 접근자라 생성 후에는 바꿀 수 없고, Equals가 값 기준으로 동작합니다.

2. 값 비교와 with

var a = new UserDto(1, "Kim");
var b = new UserDto(1, "Kim");
Console.WriteLine(a == b);        // True (class였다면 False)

var c = a with { Name = "Lee" };  // 일부만 바꾼 새 인스턴스
Console.WriteLine(c.Name);        // Lee

3. Deconstruct와 패턴 매칭

var (id, name) = a;

if (a is { Id: > 0, Name: "Kim" })
{
    // 속성 패턴
}

4. 주의할 점

  1. 컬렉션 속성은 참조 비교입니다 — 내용이 같아도 ==가 False
  2. record class는 상속 가능, record struct는 값 형식
  3. EF Core 엔티티에는 보통 쓰지 않습니다 — 생성자 바인딩·변경 추적 때문에 class가 편합니다
// 컬렉션까지 값 비교하려면 직접 구현
public record OrderDto(int Id, IReadOnlyList<string> Items)
{
    public virtual bool Equals(OrderDto? other) =>
        other is not null && Id == other.Id &&
        Items.SequenceEqual(other.Items);

    public override int GetHashCode() => HashCode.Combine(Id, Items.Count);
}

정리

  1. DTO·설정·결과 값에는 record
  2. 변경이 잦은 도메인 객체·EF 엔티티에는 class
  3. 컬렉션 속성은 값 비교가 되지 않으니 직접 구현