콘텐츠로 이동

C# 12 Primary Constructors — 간결한 생성자 선언

Primary Constructors는 C# 12에서 클래스와 구조체에 도입된 기능으로, 생성자 매개변수를 타입 선언부에 직접 정의합니다. 이전에는 레코드(record)에서만 가능했던 문법이 일반 클래스/구조체로 확대되었습니다.


// Before (C# 11 이하)
public class OrderService
{
private readonly IOrderRepository _repo;
private readonly ILogger<OrderService> _logger;
public OrderService(IOrderRepository repo, ILogger<OrderService> logger)
{
_repo = repo;
_logger = logger;
}
}
// After (C# 12)
public class OrderService(IOrderRepository repo, ILogger<OrderService> logger)
{
// repo, logger를 클래스 전체에서 직접 사용
public async Task<Order?> GetAsync(int id)
{
logger.LogInformation("Getting order {Id}", id);
return await repo.FindAsync(id);
}
}

2. 매개변수 캡처와 필드 초기화

섹션 제목: “2. 매개변수 캡처와 필드 초기화”

Primary Constructor 매개변수는 필드가 아닙니다. 필드로 저장하려면 명시적으로 할당해야 합니다.

public class Cache(int capacity)
{
// 매개변수를 필드로 저장
private readonly int _capacity = capacity;
// 매개변수를 이용한 필드 초기화
private readonly Dictionary<string, object> _store = new(capacity);
}

public class Animal(string name)
{
public string Name { get; } = name;
}
public class Dog(string name, string breed) : Animal(name)
{
public string Breed { get; } = breed;
}

// 기존 DI 패턴과 동일하게 동작
public class UserController(
IUserService userService,
ILogger<UserController> logger,
IMapper mapper)
{
[HttpGet("{id}")]
public async Task<IActionResult> Get(int id)
{
logger.LogDebug("Fetching user {Id}", id);
var user = await userService.GetByIdAsync(id);
return user is null ? NotFound() : Ok(mapper.Map<UserDto>(user));
}
}

public struct Point(double x, double y)
{
public double X { get; } = x;
public double Y { get; } = y;
public double Distance => Math.Sqrt(X * X + Y * Y);
}
var p = new Point(3, 4);
Console.WriteLine(p.Distance); // 5

public class Counter(int start)
{
private int _count = start; // start를 캡처해 필드 초기화
public void Increment() => _count++;
// 주의: start는 여전히 접근 가능하지만 _count와 다를 수 있음
public int Initial => start;
public int Current => _count;
}

매개변수를 여러 곳에서 사용하면 값이 분기될 수 있습니다. 혼동을 피하려면 필드에 저장 후 매개변수 참조를 제한하세요.


항목recordclass
매개변수 → 속성 자동 생성✗ (직접 선언)
with 표현식
Equals/GetHashCode 자동 생성
불변성 기본

Primary Constructors는 DI 의존성 주입, 간단한 값 객체, 서비스 클래스에서 생성자 보일러플레이트를 크게 줄여줍니다. 단, 매개변수가 필드가 아님을 명심하고 필요한 경우 명시적으로 필드에 저장하세요.