10. CLR 제네릭의 런타임 구현(값 형식 특수화·코드 공유·박싱 회피)

난이도 상 해설 보기 →

결함을 모두 찾고 원인·수정안·더 나은 설계를 제시하라. 마커 (A)(B) 는 주목 위치 힌트다.

결함 코드 · C#
// 주제: CLR 제네릭의 런타임 구현 — 값 형식 특수화, 코드 공유, 박싱 회피
//
// 과제: 아래 (A)~(E) 각 지점에서 "박싱(boxing)이 일어나는지"를 예측하고,
//       다음을 내부 동작으로 설명하라.
//   1) 왜 List<int> 는 int 를 박싱하지 않는데 ArrayList 는 박싱하는가?
//   2) CLR 은 제네릭을 런타임에 어떻게 구현하는가? "값 형식 인스턴스화는
//      특수화(specialization), 참조 형식 인스턴스화는 코드 공유(sharing)"가
//      무슨 뜻인가?
//   3) EqualityComparer<T>.Default 는 값 형식의 비교에서 어떻게 박싱을 피하는가?
//      반대로 제약 없는 T 에 대해 a.Equals(b) (object.Equals)는 왜 박싱하는가?

using System;
using System.Collections;
using System.Collections.Generic;

public struct Point : IEquatable<Point>
{
    public int X, Y;
    public bool Equals(Point other) => X == other.X && Y == other.Y;
    public override bool Equals(object obj) => obj is Point p && Equals(p);
    public override int GetHashCode() => unchecked(X * 397) ^ Y;
}

public static class Program
{
    static bool GenericEquals<T>(T a, T b)
        => EqualityComparer<T>.Default.Equals(a, b);     // (A) 값 형식일 때 박싱?

    static bool ObjectEquals<T>(T a, T b)
        => a.Equals(b);                                  // (B) object.Equals 경로 박싱?

    public static void Main()
    {
        ArrayList al = new ArrayList();
        al.Add(42);                                      // (C) int 추가

        List<int> li = new List<int>();
        li.Add(42);                                      // (D) int 추가

        var p1 = new Point { X = 1, Y = 2 };
        var p2 = new Point { X = 1, Y = 2 };

        GenericEquals(p1, p2);                           // (A) 호출
        ObjectEquals(p1, p2);                            // (B) 호출

        Dictionary<int, string> map = new Dictionary<int, string>();
        map[7] = "seven";                                // (E) 키(int) 해시/비교
    }
}
내 리뷰 · C#
내 답안 · 자동 저장

작성 후 위 해설 보기에서 모범 해설과 대조하세요.