46. params 가변 인자: 오버로드 해석과 호출당 배열 할당
난이도 중내 리뷰 · C#
해설 · C#
해설 — params 가변 인자: 오버로드 해석과 호출당 배열 할당
난이도: 중
요약
params 는 문법 설탕이다. 컴파일러는 흩어진 인자들을 호출 지점에서 새 배열로 묶어(expanded form)
전달한다. 일반(고정 인자) 오버로드가 적용되면 params 오버로드보다 항상 우선한다. 인자가 여러 개면
호출마다 배열이 힙에 할당되지만, 인자 0개는 컴파일러가 Array.Empty<T>() 로 처리해 할당이 없다.
출력
exact(int,int)
params(len=3)
params(len=0)
params(len=2)
hit / argc=2
핵심 개념 / 각 호출 분석
- (1)
Which(1,2)→exact(int,int):Which(int,int)는 일반 형식(normal form) 으로,Which(params int[])는 확장 형식(expanded form) 으로만 적용된다. 오버로드 해석은 일반 형식으로 적용되는 후보를 확장 형식으로만 적용되는 후보보다 더 낫다 고 판정한다 → 고정 오버로드 선택. 배열 할당 없음. - (2)
Which(1,2,3)→params(len=3): 고정 오버로드가 없어params확장 형식만 적용. 컴파일러가new int[]{1,2,3}를 호출마다 새로 할당해 넘긴다. → int[3] 힙 할당 1회. - (3)
Which()→params(len=0): 확장 형식, 원소 0개. Roslyn 은 빈 배열에 대해Array.Empty<int>()(프로세스 전역 캐시된 싱글턴)를 넘기므로 할당 없음. - (4)
Which(new int[]{1,2})→params(len=2):int[]를 직접 넘기면params매개변수의 일반 형식(배열 하나를 그대로 받는 형태)으로 바인딩된다. 컴파일러는 확장하지 않고 넘긴 배열을 그대로 사용한다. 여기서 배열 할당은new int[]{1,2}리터럴 자체이지, params 확장 때문이 아니다. - (5)
Log("hit", 42, "orc")→hit / argc=2:params object[]이므로object[]{ (object)42, "orc" }가 할당된다. 값 형식42는object로 담기며 박싱된다(힙에 박스 객체 1개 + object[2] 배열 1개).
단계별 내부 동작
- 컴파일러가 호출 지점에서 각 인자의 형식 변환 가능성으로 후보 집합을 만든다.
- 각 후보를 "일반 형식으로 적용 가능한가 / 확장 형식으로만 적용 가능한가" 로 분류한다.
- 더 나은 함수 멤버(better function member) 규칙: 일반 형식 후보 > 확장 형식 후보. 그래서 (1)에서 고정 오버로드가 이긴다.
- 확장 형식이 선택되면, 컴파일러가
newarr+ 원소 대입 IL 을 삽입해 배열을 만든다. 인자 0개는Array.Empty<T>()로 최적화한다.
흔한 오해·함정
- "params 는 공짜" — 아니다. 인자 1개 이상이면 호출마다 배열 할당이 일어난다. 핫 패스(틱 루프·로깅)
에서
params object[]는 배열 + 박싱으로 GC 압박을 만든다. - 핫 경로 회피 패턴: 인자 수별 고정 오버로드(
Log(string),Log(string, object), ...)를 제공하고 마지막에params폴백을 두면, 흔한 소량 인자 호출에서 할당·박싱을 없앤다(BCL 의 여러 API 가 이 방식). - 명시적 배열 vs 확장: 배열을 직접 넘기면 재사용되지만, 그 배열을 메서드가 보관·수정하면 호출자 배열이 오염될 수 있다.
- null 전달:
Which(null)은int[]오버로드엔 안 맞지만params object[]류에선args == null(빈 배열 아님)이 되어NullReferenceException을 유발할 수 있다.
면접 포인트
params의 일반 형식 vs 확장 형식과 오버로드 "betterness"(고정 오버로드 우선).- 호출당 배열 할당·
Array.Empty<T>()최적화·params object[]의 박싱 비용과 핫 패스 회피 패턴. - 명시적 배열 전달 시 확장이 일어나지 않는다는 점과 그 부작용(배열 공유).