숏컷 코드
public class Player
{
public string Name { get; }
public int Level { get; private set; }
public Player(string name) : this(name, 1) { }
public Player(string name, int level)
{
Name = name;
Level = level;
}
}
var beginner = new Player("Mina");
var veteran = new Player("Jin", 50);문법
어떤 생성 형태가 있나
| 형태 | 언제 떠올리나 |
|---|---|
| 매개변수 없는 생성자 | 프레임워크/직렬화 요구가 있을 때 |
| 오버로드 생성자 | 필수값은 같고 입력 조합만 다를 때 |
: this(...) 체이닝 | 초기화 규칙을 한 곳에 모을 때 |
| primary constructor | 클래스 선언이 짧고 의존성 주입이 단순할 때 |
| 정적 생성자 | 타입 수준 준비 작업이 한 번만 필요할 때 |
생성자의 역할: 처음부터 유효한 상태
생성자의 핵심 목적은 객체가 만들어지는 순간 모순 없는 초기 상태를 보장하는 것입니다. 필수 데이터를 생성자 매개변수로 받으면, 불완전한 상태로 존재하는 객체를 원천 차단할 수 있습니다.
// ❌ 필수 값이 없어도 만들 수 있고, 나중에 설정을 깜빡할 수 있음
var order = new Order();
order.CustomerId = 42; // 설정하지 않으면 OrderId가 0인 채로 사용됨
// ✅ 필수 값 없이는 객체 생성 자체가 불가
var order = new Order(customerId: 42, productId: 7);생성자 오버로딩
같은 타입을 다양한 방식으로 초기화할 때 씁니다. 각 오버로드는 서로 다른 매개변수 조합을 받습니다.
public class Rect
{
public double Width, Height;
public Rect(double size) : this(size, size) { } // 정사각형
public Rect(double width, double height)
{
Width = width; Height = height;
}
}this() — 생성자 체이닝
: this(...) 로 같은 클래스의 다른 생성자를 먼저 호출합니다. 초기화 로직이 여러 생성자에 중복되는 것을 막는 가장 간단한 방법입니다.
public Player(string name) : this(name, level: 1) { }
// ↑ 먼저 Player(string, int)를 호출한 뒤 이 본문 실행// ❌ 각 생성자마다 검증 로직을 반복
public User(string name)
{
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException();
Name = name;
Role = "user";
}
public User(string name, string role)
{
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException();
Name = name;
Role = role;
}
// ✅ 공통 초기화는 한 생성자에 모음
public User(string name) : this(name, "user") { }
public User(string name, string role)
{
if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException();
Name = name;
Role = role;
}Primary constructor (C# 12+)
클래스 선언줄에 매개변수를 바로 씁니다. 매개변수가 클래스 전체에서 접근 가능하고, 본문을 별도로 쓰지 않아도 됩니다. 단순한 데이터 홀더나 서비스 주입에 특히 간결합니다.
public class OrderService(IRepository repo, ILogger logger)
{
public void Process(Order order)
{
logger.Log("processing");
repo.Save(order);
}
}정적 생성자
인스턴스가 처음 만들어지기 전, 또는 정적 멤버에 처음 접근하기 전에 딱 한 번 자동 호출됩니다. 정적 필드 초기화, 설정 로드처럼 클래스 수준의 준비 작업에 씁니다.
public class Config
{
public static readonly string AppName;
static Config()
{
AppName = Environment.GetEnvironmentVariable("APP_NAME") ?? "RefDock";
}
}체크포인트
| 패턴 | 설명 |
|---|---|
| 기본 생성자 | 매개변수 없음. 클래스에 생성자가 없으면 컴파일러가 자동 생성 |
| 오버로딩 | 다양한 초기화 방식을 제공 |
: this(...) | 중복 초기화 코드를 한 곳에 모음 |
primary constructor | 선언줄 매개변수, C# 12+ |
static 생성자 | 클래스당 한 번, 타입 초기화 전용 |
주의할 점
생성자에서 너무 많은 일을 하면 테스트와 재사용이 어려워집니다. 파일 읽기, 네트워크 요청처럼 실패 가능성이 있는 작업은 생성자보다 팩토리 메서드나 초기화 메서드로 빼는 편이 좋습니다.
정적 생성자에서 예외가 발생하면 해당 타입은 TypeInitializationException으로 감싸인 채 프로세스가 살아있는 동안 다시는 초기화되지 않습니다. 정적 생성자는 가능한 한 단순하게 유지하세요.
매개변수 없는 생성자를 편의상 추가하면 "불완전한 상태의 객체"가 다시 들어올 수 있습니다. ORM이나 serializer 같은 외부 요구가 아니라면, 필수 값이 있는 타입은 생성자에서도 그 요구를 그대로 드러내는 편이 안전합니다.
참고 링크
2 sources