숏컷 코드
public class Player
{
public string Name { get; set; } = ""; // 읽기/쓰기
public int Score { get; private set; } // 외부 읽기, 내부 쓰기
public int Level { get; init; } // 생성 시점에만 쓰기
// 계산 프로퍼티 — 저장 없이 매번 계산
public string Title => Score >= 1000 ? "Pro" : "Novice";
}문법
어떤 프로퍼티 형태가 있나
| 형태 | 의미 |
|---|---|
{ get; set; } | 읽기·쓰기 모두 가능 |
{ get; private set; } | 외부 읽기, 내부 쓰기 |
{ get; } | 생성자에서만 초기화 가능한 읽기 전용 |
{ get; init; } | 초기화식에서만 설정 |
required ... { get; init; } | 생성 시 반드시 값 지정 |
=> expression | 계산 프로퍼티 |
필드 vs 프로퍼티
퍼블릭 필드와 자동 구현 프로퍼티는 외부에서 쓰는 방법이 같아 보이지만, 구조적으로 다릅니다.
public class Point
{
public int X; // 필드: 직접 접근, 나중에 검증 추가 불가
public int Y { get; set; } // 프로퍼티: getter/setter로 감싸짐
}프로퍼티는 나중에 set 안에 검증 로직을 추가하거나 접근 범위를 좁혀도 호출하는 코드를 바꾸지 않아도 됩니다. 필드로 시작했다가 프로퍼티로 바꾸면 바이너리 호환성이 깨지고, 인터페이스나 리플렉션 코드도 수정이 필요합니다.
접근자 조합
public int Score { get; set; } // 어디서나 읽기·쓰기
public int Score { get; private set; } // 외부 읽기, 클래스 내부 쓰기
public int Score { get; protected set; }// 외부 읽기, 파생 클래스까지 쓰기
public int Score { get; } // 생성자에서만 설정 가능한 읽기 전용
public int Score { get; init; } // 객체 초기화식에서만 설정 가능init — 초기화 후 불변
init은 객체 초기화식(new T { Prop = value })에서만 값을 설정할 수 있고 이후에는 읽기 전용이 됩니다. 생성자를 만들지 않으면서도 안전한 초기화를 원할 때 유용합니다.
var p = new Player { Name = "Mina", Level = 5 }; // ✅ init 가능
p.Level = 6; // ❌ 컴파일 오류 — init 이후 수정 불가required — 초기화 강제 (C# 11+)
required가 붙은 프로퍼티는 객체 생성 시 반드시 값을 지정해야 합니다. 생성자 없이도 필수 필드를 보장할 수 있습니다.
public class User
{
public required string Name { get; init; }
public required string Email { get; init; }
}
var u = new User { Name = "Mina", Email = "m@ex.com" }; // ✅
var u = new User { Name = "Mina" }; // ❌ Email 누락 — 컴파일 오류required는 "반드시 채워라"는 계약이고, init은 "초기화 시점에만 써라"는 계약입니다. 둘은 자주 같이 쓰이지만 역할은 다릅니다.
계산 프로퍼티
백킹 필드 없이 매번 계산해서 값을 반환합니다. 상태가 아닌 "파생 정보"를 표현할 때 적합합니다.
public class Rectangle
{
public double Width { get; set; }
public double Height { get; set; }
public double Area => Width * Height; // 저장 없이 계산
public bool IsSquare => Width == Height;
}체크포인트
| 형태 | 의미 |
|---|---|
{ get; set; } | 읽기·쓰기 모두 가능 |
{ get; private set; } | 외부 읽기, 내부(클래스)에서만 쓰기 |
{ get; } | 생성자에서만 초기화 가능한 읽기 전용 |
{ get; init; } | 초기화식에서만 설정, 이후 읽기 전용 |
required ... { get; init; } | 생성 시 반드시 값 지정 |
=> expression | 계산 프로퍼티, 매번 평가 |
주의할 점
계산 프로퍼티는 호출할 때마다 다시 계산됩니다. 비용이 큰 연산(DB 조회, 복잡한 계산 등)은 프로퍼티가 아니라 메서드로 표현하거나, 결과를 캐싱하는 편이 좋습니다. 프로퍼티는 "가벼운 접근"이라는 호출자의 기대를 따르는 것이 관례입니다.
required는 C# 11 이상에서만 사용 가능합니다. 이전 버전에서는 생성자 매개변수로 필수 값을 받는 방식을 써야 합니다.
검증 로직이 필요한 값을 퍼블릭 필드로 열어 두면 나중에 규칙을 추가하기 어렵습니다. 외부에서 직접 쓰는 데이터라면 처음부터 프로퍼티로 시작하는 편이 대부분 더 안전합니다.
참고 링크
2 sources