← 문제로

55. enum 내부 표현 · [Flags] · HasFlag 박싱 · 캐스팅

난이도 중
내 리뷰 · C#
해설 · C#

해설 — enum 내부 표현 · [Flags] · HasFlag 박싱 · 캐스팅

난이도: 중

요약

enum은 런타임에 기저 정수형(기본 int)의 값일 뿐이고, 이름 상수는 컴파일 타임 편의다. 따라서 열거 상수에 없는 정수도 캐스팅으로 담을 수 있다((Color)99). [Flags]는 값이 비트 조합임을 나타내는 표식으로, ToString이 조합을 이름 나열로 출력하게 하고 비트 연산으로 집합처럼 다루게 한다. HasFlag는 (p & flag) == flag를 하되 인자를 Enum으로 받아 박싱이 발생해 핫패스에서 비용이 될 수 있다.

예측 출력

3
Read, Write
True
False
99
False
System.Byte
True
  • (1) Read|Write = 1|2 = 3.
  • (2) [Flags]라 ToString이 "Read, Write"로 조합 출력.
  • (3)(4) HasFlag: Write 포함 True, Exec 미포함 False.
  • (5) 99는 이름이 없어 숫자 그대로 "99" 출력.
  • (6) IsDefined: 99는 정의 안 됨 → False.
  • (7) Color의 기저형은 byte → System.Byte.
  • (8) 리터럴 0은 어떤 enum으로도 암시적 변환되어 Perm.None과 동일 → True.

핵심 개념

  • 기저형: 기본 int. : byte/: long 등으로 지정 가능. 값 범위·크기·직렬화에 영향.
  • 정의되지 않은 값: enum은 정수라 유효성 검사가 자동이 아님 → 경계에서 IsDefined/화이트리스트로 검증해야 안전.
  • [Flags]: 각 값이 2의 거듭제곱이어야 조합이 유효. ToString/파싱이 조합을 지원.

단계별 내부 동작

  • Perm.Read | Perm.Write: 정수 OR → 3. 저장은 int 하나.
  • HasFlag(flag): 내부적으로 두 값을 Enum으로 다뤄 박싱(값형 → 힙 객체) 후 비트 검사. 매 틱 수천 번 호출하면 GC 압박. 핫패스에선 (p & Perm.Write) == Perm.Write 직접 비트 연산이 무할당.
  • (Color)99: byte 범위 내 정수를 그대로 저장. 이름 매핑이 없어 ToString은 숫자.

흔한 오해·함정

  • "enum 파라미터는 항상 유효한 값" — 아니다. 네트워크/DB에서 온 값을 캐스팅하면 정의 밖 값이 들어올 수 있다 → IsDefined 또는 명시적 검증.
  • HasFlag의 박싱: 성능 민감 경로에서 비트 연산으로 대체.
  • [Flags] 없이 비트 조합을 쓰면 ToString이 숫자로만 나오고 의도가 흐려진다.
  • 리터럴 0의 암시적 변환 때문에 None=0 관례가 유용(기본값·비교).

면접 포인트

  • enum이 런타임엔 정수라는 점과 "정의 밖 값" 위험, 경계 검증의 필요성.
  • HasFlag 박싱 비용과 핫패스에서의 대안(직접 비트 연산).
  • 기저형 지정의 효과(크기/직렬화)와 [Flags] 관례(2의 거듭제곱, None=0).