23. [Flags] enum 의 내부 표현과 Enum.HasFlag 의 박싱 비용
난이도 중 해설 보기 →
결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커
(A)(B) 는 주목 위치 힌트다.
결함 코드 · C#
// 주제: [Flags] enum 의 내부 표현(정수 기반 값 타입)과, Enum.HasFlag 가 내부적으로
// 무엇을 하는지 — 왜 비트 AND 연산자 대신 쓰면 성능 함정이 되는가.
//
// 게임서버에서 흔한 패턴: 엔티티/세션의 상태를 [Flags] enum 비트마스크로 표현하고
// (예: 마비/은신/무적 등 버프 상태), 매 틱마다 수만 개 엔티티에 대해 상태를 검사한다.
//
// 다음을 예측·설명하라:
// (1) StatusFlags 는 값 타입(struct 계열)인 enum 인데, HasFlag(StatusFlags) 는
// 매개변수 타입이 Enum(추상 기반 클래스)이다. 호출부에서 (A) 지점마다 어떤 변환이
// 일어나는가? 그 변환은 힙 할당을 유발하는가?
// (2) (B) 의 비트 AND 방식과 (A)의 HasFlag 방식은 같은 결과를 내는가? 성능 특성이
// 왜 다른가? (박싱 여부, 가상 호출 여부)
// (3) enum 의 밑바탕 타입(underlying type)은 기본이 무엇이고, 이를 바꾸면(byte 등)
// 메모리 사용량/비교 연산에 어떤 영향이 있는가?
// (4) 매 틱 수만 번 호출되는 핫 패스에서 (A) 방식을 쓰면 GC 에 어떤 부담을 주는지,
// 그리고 왜 릴리스 빌드에서도 이 오버헤드가 사라지지 않는지 설명하라.
using System;
[Flags]
public enum StatusFlags
{
None = 0,
Stunned = 1 << 0,
Silenced = 1 << 1,
Invisible = 1 << 2,
Invincible= 1 << 3,
}
public static class StatusChecker
{
public static bool IsStunnedViaHasFlag(StatusFlags status)
{
// (A) HasFlag 의 매개변수는 Enum 타입 — status 는 여기로 어떻게 전달되는가?
return status.HasFlag(StatusFlags.Stunned);
}
public static bool IsStunnedViaBitwise(StatusFlags status)
{
// (B) 순수 비트 연산 — 힙 할당 없이 정수 AND 로 끝난다
return (status & StatusFlags.Stunned) == StatusFlags.Stunned;
}
// 매 틱마다 수만 개 엔티티를 검사하는 핫 패스를 흉내
public static int CountStunned(StatusFlags[] allEntities, bool useHasFlag)
{
int count = 0;
foreach (var s in allEntities)
{
bool stunned = useHasFlag ? IsStunnedViaHasFlag(s) : IsStunnedViaBitwise(s);
if (stunned) count++;
}
return count;
}
} 내 리뷰 · C#
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.