13. foreach의 열거자 패턴, struct 열거자 박싱, 버전 토큰
난이도 중 해설 보기 →
결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커
(A)(B) 는 주목 위치 힌트다.
결함 코드 · C#
// 주제: foreach 의 컴파일러 패턴과 열거자(enumerator) — struct 열거자의 무할당, 박싱,
// 그리고 열거 중 컬렉션 변경 시의 동작(버전 토큰).
//
// 다음을 예측·설명하라:
// (1) foreach (var x in list) 는 어떤 멤버 호출들로 풀리나? (GetEnumerator/MoveNext/Current/Dispose)
// 그리고 foreach 가 IEnumerable 인터페이스가 "꼭" 필요한가?
// (2) List<int> 를 직접 foreach 할 때와, 같은 리스트를 IEnumerable<int> 로 받아 foreach 할 때
// 힙 할당이 어떻게 다른가? (struct 열거자 vs 박싱)
// (3) (A): foreach 도중 컬렉션을 수정하면 무슨 일이 일어나나? 내부적으로 어떻게 감지하나?
// (4) (B): struct 열거자를 변수에 복사해 MoveNext 하면 원본은 어떻게 되나?
using System.Collections;
using System.Collections.Generic;
public static class Demo
{
// (1)(2) 구체 타입 vs 인터페이스
public static int SumConcrete(List<int> xs)
{
int s = 0;
foreach (var x in xs) s += x; // List<int>.Enumerator (struct) 사용
return s;
}
public static int SumInterface(IEnumerable<int> xs)
{
int s = 0;
foreach (var x in xs) s += x; // IEnumerator<int> (박싱된 열거자)
return s;
}
// (3) 열거 중 수정
public static void MutateWhileEnumerating(List<int> xs)
{
foreach (var x in xs)
{
if (x == 2) xs.Add(999); // (A) 열거 도중 컬렉션 변경
}
}
// (4) struct 열거자 복사
public static void CopyEnumerator(List<int> xs)
{
List<int>.Enumerator e1 = xs.GetEnumerator();
List<int>.Enumerator e2 = e1; // (B) struct 복사
e2.MoveNext(); // e2 만 전진? e1 은?
}
} 내 리뷰 · C#
내 답안 · 자동 저장
작성 후 위 해설 보기에서 모범 해설과 대조하세요.