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 선택 기준(정보 손실·의외성)과 암시적 변환 남용의 위험.