← 문제로

49. 사용자 정의 변환 연산자(implicit/explicit)와 오버로드 해석

난이도 중
내 리뷰 · C#
해설 · C#

해설 — 사용자 정의 변환 연산자(implicit/explicit)와 오버로드 해석

난이도: 중상

요약

implicit/explicit operator 는 타입 간 변환을 사용자 정의한다. 암시적 변환은 대입·인자 전달에서 자동 적용되고, 명시적 변환은 캐스트 문법이 있어야 한다. 오버로드 해석은 표준 변환을 사용자 정의 변환보다 선호하며, 한 변환 경로에는 사용자 정의 변환을 최대 한 번만 넣을 수 있다(앞뒤에 표준 변환은 허용). 예측 출력: 5m / 5 / F(double) / F(Meters) / F(double) / 10m.

핵심 개념

  • implicit vs explicit: implicit operator Meters(double) 은 Meters m = 5.0; 처럼 자동 적용. explicit operator double(Meters) 은 (double)m 처럼 캐스트를 요구(정보 손실·의외성 가능성이 있을 때 explicit 권장).
  • 표준 변환 > 사용자 정의 변환: 오버로드 후보를 비교할 때, 표준(내장) 변환만 쓰는 후보가 사용자 정의 변환을 요구하는 후보보다 "더 나은 변환"으로 우선된다.
  • 단일 사용자 정의 변환 규칙: S → T 를 사용자 정의 변환 하나로 잇되, 그 앞/뒤에 표준 변환을 각각 한 번 붙일 수 있다. 사용자 정의 변환을 두 번 연쇄하는 것은 불가.

단계별 내부 동작

  • L1 Meters m = 5.0 → 암시적 double→Meters. m.V = 5.0. ToString() → 보간 $"{V}m" 에서 double 5.0 은 "5" 로 출력 → "5m".
  • L2 (double)m → 명시적 Meters→double → 5.0. WriteLine(double) → "5".
  • L3 F(3.0) → 인자 double, F(double) 정확 일치 → "F(double)".
  • L4 F(m) → 인자 Meters, F(Meters) 정확 일치 → "F(Meters)".
  • L5 F(i) (i 는 int) → 두 후보:
    • F(double): int→double 은 표준(내장) 암시적 수치 변환.
    • F(Meters): int→Meters 는 int→double(표준) + double→Meters(사용자 정의) = 사용자 정의 변환 포함. 표준 변환만 쓰는 F(double) 이 더 나은 변환으로 우선 → "F(double)".
  • L6 Meters m2 = 10 → int→Meters. int→double(표준) 뒤에 double→Meters(사용자 정의 한 번). 사용자 정의 변환이 정확히 한 번이라 규칙 충족 → 컴파일 OK. m2.V = 10.0 → "10m".

흔한 오해·함정

  • 암시적 변환 남용: implicit 이 너무 많으면 의도치 않은 변환이 조용히 일어나 버그(단위 혼동·정밀도 손실). 손실·의외성 있으면 explicit 로.
  • 이중 사용자 정의 변환 불가: A→B, B→C 가 각각 사용자 정의여도 A→C 는 자동으로 이어지지 않는다(한 번만 허용). 컴파일 오류로 나타난다.
  • 오버로드 모호성: 여러 후보가 서로 다른 사용자 정의 변환으로 동등하게 적용되면 CS0121(모호) 오류.
  • 박싱 함정: struct↔object/인터페이스 변환은 사용자 정의가 아니라 박싱이며, 사용자 정의 변환과 규칙이 다르다.
  • is/as 와 무관: 사용자 정의 변환은 캐스트/대입 문맥에서만. as 는 참조/박싱 변환만 본다.

면접 포인트

  • 표준 변환이 사용자 정의 변환보다 우선되는 오버로드 규칙(L5의 핵심).
  • "한 경로에 사용자 정의 변환 한 번" 규칙과 앞뒤 표준 변환 허용(L6).
  • implicit vs explicit 선택 기준(정보 손실·의외성)과 암시적 변환 남용의 위험.