26. Nullable<T> 내부 구조와 boxing 특수 처리, lifted operator
난이도 중 해설 보기 →
결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커
(A)(B) 는 주목 위치 힌트다.
결함 코드 · C#
// 문제 26 — Nullable<T> 내부 구조와 boxing 시의 특수 처리, lifted operator
//
// 아래는 게임 서버에서 플레이어의 "선택적 보너스 스탯"을 int?(Nullable<int>)로
// 표현하고, 이를 object로 박싱/언박싱하거나 서로 비교·연산하는 코드다.
//
// (A) Nullable<T>는 실제로 HasValue(bool)와 Value(T) 두 필드만 가진 struct다.
// (B) hasBonus 가 null인 상태에서 boxing이 일어나는 지점이 있다.
// (C) 들어올림 연산자(lifted operator)로 처리되는 비교/산술 연산이 있다.
//
// 과제:
// 1. bonus1 (값이 있는 int?)을 object로 박싱한 뒤 다시 언박싱하는 코드에서,
// 박싱된 object의 실제 런타임 타입(GetType())이 무엇으로 나오는지 예측하라.
// 2. bonus2 (값이 없는, 즉 null인 int?)을 object로 박싱하면 그 결과가
// 정확히 어떤 값/타입이 되는지 예측하라("boxed Nullable<int> with HasValue=false"
// 같은 객체가 되는지, 아니면 다른 무언가가 되는지).
// 3. boxedNull == null 비교 결과와 boxedNull is int 패턴 매칭 결과를 예측하라.
// 4. bonus1 + bonus2 (들어올림 산술 연산자)의 결과와, bonus1 == bonus2,
// bonus2 == null 의 결과를 각각 예측하라.
// 5. GetValueOrDefault()와 그냥 Value를 사용했을 때(HasValue가 false인 경우)의
// 차이를 예측하라(예외가 나는지, 어떤 예외인지).
//
// 아래 코드는 콘솔 앱에서 컴파일·실행 가능하다 (C# 8+ 기준, dotnet run).
using System;
class BonusStatSystem
{
static void Main()
{
int? bonus1 = 15;
int? bonus2 = null;
Console.WriteLine("--- 1. 값이 있는 Nullable<int> 박싱/언박싱 ---");
object boxed1 = bonus1;
Console.WriteLine($"boxed1.GetType() = {boxed1.GetType()}");
int unboxed1 = (int)boxed1;
Console.WriteLine($"unboxed1 = {unboxed1}");
Console.WriteLine("--- 2. 값이 없는(null) Nullable<int> 박싱 ---");
object boxedNull = bonus2;
Console.WriteLine($"boxedNull == null : {boxedNull == null}");
Console.WriteLine($"boxedNull is int : {boxedNull is int}");
Console.WriteLine("--- 3. 들어올림 연산자(lifted operator) ---");
int? sum = bonus1 + bonus2;
Console.WriteLine($"bonus1 + bonus2 = {(sum.HasValue ? sum.Value.ToString() : "null")}");
bool eq1 = bonus1 == bonus2;
bool eq2 = bonus2 == null;
Console.WriteLine($"bonus1 == bonus2 : {eq1}");
Console.WriteLine($"bonus2 == null : {eq2}");
int? bonus3 = 15;
bool eq3 = bonus1 == bonus3;
Console.WriteLine($"bonus1 == bonus3 : {eq3}");
Console.WriteLine("--- 4. GetValueOrDefault() vs Value ---");
int safeValue = bonus2.GetValueOrDefault();
Console.WriteLine($"bonus2.GetValueOrDefault() = {safeValue}");
try
{
int riskyValue = bonus2.Value;
Console.WriteLine($"bonus2.Value = {riskyValue}");
}
catch (InvalidOperationException e)
{
Console.WriteLine($"bonus2.Value 접근 시 예외 발생: {e.GetType().Name}");
}
Console.WriteLine("--- 5. typeof(int?) 와 Nullable.GetUnderlyingType ---");
Type nullableType = typeof(int?);
Console.WriteLine($"typeof(int?) = {nullableType}");
Console.WriteLine($"Nullable.GetUnderlyingType(typeof(int?)) = {Nullable.GetUnderlyingType(nullableType)}");
}
} 내 리뷰 · C#
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.