5

과부하 해결로 이상한 동작을 감지했습니다.오버로드, 일반 형식 유추 및 '매개 변수'키워드

public static void DoSomething<T>(params T[] items) 
{ 
    // Whatever 

    // For debugging 
    Console.WriteLine("DoSomething<T>(params T[] items)"); 
} 
: 편의를 위해 내가이 오버로드를 추가 할 수 있도록

public static void DoSomething<T>(IEnumerable<T> items) 
{ 
    // Whatever 

    // For debugging 
    Console.WriteLine("DoSomething<T>(IEnumerable<T> items)"); 
} 

지금, 나는이 방법은 종종 명시 적 인수 적은 수의 호출 할 것이라는 점을 알고있다 :

나는 다음과 같은 방법을 가지고 있다고 가정

지금 나는이 메소드를 호출하려고 :

var items = new List<string> { "foo", "bar" }; 
DoSomething(items); 
DoSomething("foo", "bar"); 

그러나 두 경우 모두

의 과부하가 params으로 호출됩니다. List<T>의 경우에 IEnumerable<T> 오버로드가 호출 될 것으로 예상 했으므로 (적어도 나에게) 더 나은 일치로 보입니다.

이 동작이 정상입니까? 아무도 그것을 설명 할 수 있을까? MSDN 문서에서 이에 대한 명확한 정보를 찾을 수 없습니다 ... 여기에 관련된 과부하 해결 규칙은 무엇입니까?

답변

9

C# 3.0 사양의 7.4.3 절이 관련 비트입니다. 기본적으로 매개 변수 배열이 확장되고, 그래서 당신은 비교하는 :

public static void DoSomething<T>(T item) 

public static void DoSomething<T>(IEnumerable<T> item) 

첫 경기에 대한 TList<string> 것으로 추정되며, 두 번째 경기를 위해 T는 것으로 추정된다 .

이제 매개 변수 유형에 대한 인수와 관련된 변환을 고려하십시오. 첫 번째 매개 변수 유형은 List<string>에서 List<string>입니다. 두 번째로는 List<string>에서 IEnumerable<string>입니다. 첫 번째 변환은 7.4.3.4의 규칙에 의해 두 번째 변환보다 낫습니다.

반 직관적 비트는 유형 유추입니다. 당신이 방정식에서 그것을 가지고가는 경우에 당신이 그것을가 예상대로 작동합니다 : 그 시점에서

var items = new List<string> { "foo", "bar" }; 
DoSomething<string>(items); 
DoSomething<string>("foo", "bar"); 

, 각 호출에 하나의 적용 기능 멤버가있다.

+0

감사합니다. 존, 정확히 내가 필요한 설명입니다. 원하는대로 작동하도록하는 몇 가지 해결 방법이 있습니까? 그렇지 않다면 다른 이름을 사용해야 할 것입니다 ... –

+0

예, 제네릭 형식 매개 변수를 명시 적으로 지정하면 작동하는 것으로 나타났습니다. 하지만 타입 유추의 이점을 잃어 버렸습니다 ... –

+4

명확성을 위해서만 다른 이름을 사용하는 것이 좋습니다 - 또는 하나 이상의 항목으로 만 사용하려는 경우'(T first, params T [] others)' –