2011-02-05 2 views
18

나는 다른 일이 눈치 두 개의 오버로드 된 메서드가 있다고 가정 :방법 과부하 해상도는

public void Print<T>(IEnumerable<T> items) { 
    Console.WriteLine("IEnumerable T"); 
} 
public void Print<T>(T item) { 
    Console.WriteLine("Single T"); 
} 

이 코드 :

public void TestMethod() { 
    var persons = new[] { 
     new Person { Name = "Yan", Age = 28 }, 
     new Person { Name = "Yinan", Age = 28 } 
    }; 
    Print(persons); 
    Print(persons.ToList()); 
} 

인쇄 :

Single T 
Single T 

Person[]List<Person>T과 더 일치합니까? 이 경우에는 IEnumerable<T>보다?

감사합니다,

UPDATE : 다른 과부하가있는 경우 또한,

public void Print<T>(List<T> items) { 
    Console.WriteLine("List T"); 
} 

Print(persons.ToList());

실제로 List T 대신 Single T 인쇄됩니다.

+2

'Print (persons as IEnumerable );를 호출하면 다른 메소드를 호출해야합니다.제네릭 메서드 검색은'Person []'에서'IEnumerable '로의 암시 적 캐스트를 수행하지 않습니다. 'person.ToList()'를 호출 할 때 직접 타입은'List '(암시 적 캐스트가 필요 없음)입니다. –

+0

+1 나는이 문제에 대해 조금만 놀랐다. – Dan

답변

17

질문의 첫 번째 부분 (목록 별 과부하가없는)은 쉽습니다. 먼저 두 호출에 대해 동일하게 작동하기 때문에 Array 호출을 고려해 보겠습니다.

먼저 형식 유추에서 호출의 가능한 두 가지 일반 구현 인 Print<Person[]>(Person[] items)Print<Person>(IEnumerable<Person> items)을 생성합니다.

그런 다음 두 번째는 암시 적 변환이 필요하기 때문에 과부하 해결이 성공합니다. 첫 번째 것은 암시 적 변환을 요구하기 때문에 (C# 스펙의 7.4.2.3 참조). List 변형에서도 동일한 메커니즘이 작동합니다.

추가 된 오버로드로 인해 목록 호출에 세 번째로 발생할 수있는 과부하가 생성됩니다 (Print<Person>(List<Person> items)). 인수는 다시 Print<List<Person>>(List<Person> items)하지만와 동일 섹션 7.4.3.2는 경우 (형식 인수의 같은 수의) 언어

재귀 적으로 해상도가, 구축 된 유형이 다른 구성 유형보다 더 구체적입니다 제공 최소한 하나의 유형 인수가 더 구체적이며 유형 인수가 다른 유형 인수가 해당 유형 인수보다 구체적이지 않은 경우.

는 그래서 Print<Person> 과부하는 Print<List<Person>> 과부하보다 더 구체적이며 더 암시 적 변환이 필요 없기 때문에 목록 버전은 IEnumerable을 이긴다.

+0

감사합니다. – theburningmonk

3

제네릭 Print(Person[] item)Print(List<Person> item)에서 생성 된 메서드는 IEnumerable<T>보다 더 적합합니다. 일반 템플릿 Print<T>(T item)Print(Person[] item)Print(List<Person> item) (편집에서 잘, 어떤 유형 나타내는 List<Person>)로 컴파일 얻을 것이다, 그래서

컴파일러는, 당신의 형식 인수를 기반으로하는 방법을 생성한다. 따라서 메서드 호출은 컴파일러에서 Print(IEnumerable<Peson>) 구현이 아닌 직접 형식을 사용하는 특정 메서드로 확인됩니다.

+0

즉, 인쇄물은 T가 무엇이든 될 수 있으므로 항상 가장 잘 맞는 것으로 간주됩니까? 그러나 Print (목록 항목) 메서드를 추가하면 Print (persons.ToList)에 대해 호출되는 메서드입니다. – theburningmonk

+0

또한 Eric Lippert의 블로그 게시물에 따르면 C# generics가 http :// /blogs.msdn.com/b/ericlippert/archive/2009/07/30/generics-are-not-templates.aspx 당신이 설명한 것은 C++의 템플릿입니다. 암시 적 캐스팅에 대한 언급 덕분에 – theburningmonk