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).