9. 델리게이트/이벤트: 멀티캐스트 예외, 구독 동일성, 구독 누수
난이도 상 해설 보기 →
결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커
(A)(B) 는 주목 위치 힌트다.
결함 코드 · C#
// ============================================================================
// [내부동작 문제] C# - 델리게이트/이벤트: 멀티캐스트 호출·예외, 구독 동일성과 누수
// ----------------------------------------------------------------------------
// 주제:
// 멀티캐스트 델리게이트의 호출 순서와 "중간 핸들러가 예외를 던지면" 나머지 핸들러가
// 어떻게 되는지, 그리고 이벤트 구독(+=)/해지(-=)가 델리게이트 "동일성"에 어떻게 의존하는지
// (메서드 그룹 vs 인라인 람다)와 그로 인한 구독 누수(메모리 릭)를 예측하고 설명한다.
//
// 과제:
// 1) Part A: 세 핸들러 중 두 번째가 예외를 던질 때, 출력되는 줄과 순서를 예측하라.
// h3 는 실행되는가? 예외는 어디서 잡히는가?
// 2) Part B: 메서드 그룹 Named 와 인라인 람다를 구독한 뒤 각각 -= 로 해지를 시도한다.
// 두 번의 count 출력과 마지막 Fire() 의 출력을 예측하라. 인라인 람다 해지가
// "되는지/안 되는지"와 그 이유(델리게이트 인스턴스 동일성)를 설명하라.
// 3) 장수(long-lived) 퍼블리셔가 단명(short-lived) 구독자의 메서드를 구독했을 때
// 구독을 해지하지 않으면 왜 메모리 누수가 되는지, 게임서버 관점에서 설명하라.
// ※ 먼저 예측을 적은 뒤 answer.md 와 대조할 것.
// ============================================================================
using System;
public sealed class EventBus
{
public event Action OnEvent;
public void Fire() => OnEvent?.Invoke();
public int HandlerCount => OnEvent?.GetInvocationList().Length ?? 0;
}
public static class Program
{
static void Named() => Console.WriteLine("named");
public static void Main()
{
// ---- Part A: 멀티캐스트 호출 중 예외 ----
var a = new EventBus();
a.OnEvent += () => Console.WriteLine("h1");
a.OnEvent += () => { Console.WriteLine("h2"); throw new InvalidOperationException("boom"); };
a.OnEvent += () => Console.WriteLine("h3");
try { a.Fire(); }
catch (Exception e) { Console.WriteLine($"caught: {e.Message}"); }
Console.WriteLine("---");
// ---- Part B: 구독/해지의 동일성 ----
var b = new EventBus();
b.OnEvent += Named; // 메서드 그룹
b.OnEvent += () => Console.WriteLine("inline"); // 인라인 람다 (참조 보관 안 함)
Console.WriteLine($"count={b.HandlerCount}");
b.OnEvent -= Named; // 해지 시도 (1)
b.OnEvent -= () => Console.WriteLine("inline"); // 해지 시도 (2): 새 람다
Console.WriteLine($"count={b.HandlerCount}");
b.Fire();
}
} 내 리뷰 · C#
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.