본문 바로가기
C#

C# “??는 ‘null이면 우변’ — 안전한 기본값 지정의 한 줄 공식”

by 공부봇 2025. 10. 10.
반응형

좋은 질문이에요! 말씀하신 생성자에서의 ??는 **null 병합 연산자(null-coalescing operator)**입니다. 코드 조각을 기준으로 교재식으로 정리해 드릴게요.


1) 왜 생겼는가 — “null이면 대체값을 쓰자”

메서드 인자나 계산 결과가 null일 수도 있는 상황에서, 매번 if (x == null) ...를 쓰면 코드가 장황해집니다. 그래서 *“좌변이 null이면 우변을 대신 쓰자”*라는 패턴을 한 줄로 쓰기 위해 ??가 생겼습니다.


2) 무엇인가 — left ?? right의 의미

  • 정의: left가 null이 아니면 left를, null이면 right를 반환합니다.
  • 평가 순서/성능: left를 먼저 평가하고, left가 null이 아닐 때는 right는 평가하지 않습니다(지연 평가).
    → DateTime.Now 같은 값은 필요할 때만 호출돼요.

당신의 코드에서

Date     = now ?? DateTime.Now;
LotID    = lotId ?? string.Empty;
  • now는 DateTime?(nullable).
    • now에 값이 있으면 그 값을 Date로 사용(이때 결과 타입은 DateTime).
    • now가 null이면 그때만 DateTime.Now를 호출해 현재 시각을 사용.
  • lotId는 string(참조 형식).
    • lotId가 null이면 빈 문자열(string.Empty)을 사용.
    • ""(빈 문자열)는 null이 아님에 주의! (아래 실수 항목 참고)

3) 언제/어떻게 쓰는가 — 사용 패턴과 MWE

3-1. 파라미터 방어 코드

public LogEntry(eLog category, string message, string lotId = "", int cam = -1, DateTime? now = null)
{
    Date     = now ?? DateTime.Now;   // now가 없으면 현재 시각
    Category = category;
    Message  = message;
    LotID    = lotId ?? string.Empty; // lotId가 null이면 빈 문자열
    Cam      = cam;
}
  • lotId는 기본값이 ""라 호출자가 아무 것도 안 주면 빈 문자열이 들어옵니다.
    다만 호출자가 명시적으로 null을 넘기는 경우를 대비해 ?? string.Empty로 방어하는 셈입니다.

3-2. 간단 진리표 느낌

표현식 결과

null ?? X X
A ?? X (A가 null 아님) A
someNullable ?? defaultValue null이면 기본값, 아니면 원래 값

3-3. 실전 Mini Example

DateTime? overrideTime = null;
DateTime createdAt = overrideTime ?? DateTime.Now; // overrideTime 없으면 지금 시각

string? userInput = GetTextOrNull(); // 외부 입력
string safeText = userInput ?? string.Empty; // null 방지

참고: 값이 “없음(null)”과 “비어있음(예: "" 또는 0)”은 다른 의미예요. ??는 오직 null을 처리합니다.


4) 자주 하는 실수와 베스트 프랙티스

흔한 실수

  1. 빈 문자열과 null을 혼동
    • "" ?? "fallback"은 "" 그대로입니다(빈 문자열은 null이 아니므로).
    • 빈 문자열도 대체하고 싶다면 string.IsNullOrEmpty(lotId) ? "fallback" : lotId처럼 처리하세요.
  2. 우변 부작용/비용 간과
    • left ?? Expensive()에서 left가 null이 아니면 Expensive()는 호출되지 않습니다. 반대로 null일 때만 호출되므로, 우변에 무거운 연산을 둬도 안전합니다.
  3. ??와 ??= 헷갈림
    • x ?? y는 “평가”만,
    • x ??= y는 “x가 null이면 y를 대입”입니다.
    lotId ??= string.Empty; // lotId가 null일 때만 빈 문자열로 설정
    

베스트 프랙티스

  • 입력 경계에서 일찍 정규화: 생성자/팩토리에서 ??로 null을 처리해, 나머지 도메인 로직에서 null 분기를 최소화하세요.
  • 의미 분리: “없음(null)”과 “비어있음(빈 문자열/0)”을 구분해 모델링하고, 필요 시 string.IsNullOrWhiteSpace로 보강.
  • NRT(Nullable Reference Types)와 함께 사용: string?를 허용하되, 생성자 초기에 ??로 정규화하면 호출 계약이 명확해집니다.

 

반응형