2011-02-05 7 views
18

私は、他の日にこれを気づいたあなたは2つのオーバーロードされたメソッドを持っていると言う:メソッドオーバーロードの解決は

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(people as IEnumerable );を呼び出すと、他のメソッドを呼び出す必要があります。ジェネリックメソッドルックアップは 'Person []'から 'IEnumerable 'への暗黙のキャストを行いません。 'person.ToList()'を呼び出すと、あなたの直接の型は 'List '(暗黙のキャストも必要ありません)です。 –

+0

+1私はこの問題をちょっとやっています。 – Dan

答えて

17

質問の最初の部分(リスト固有の過負荷なし)は簡単です。

最初に、タイプ推論では、2つの可能な呼び出しの汎用実装、すなわちPrint<Person[]>(Person[] items)Print<Person>(IEnumerable<Person> items)が生成されます。

次に、第2のものが暗黙の変換を必要とするので、最初のものは暗黙の変換を必要とするため、オーバーロードの解像度が高くなります(C#仕様の7.4.2.3を参照してください)。同じ仕組みがListバリアントで機能します。

追加されたオーバーロードでは、リスト呼び出しで3番目の可能なオーバーロードが生成されます。Print<Person>(List<Person> items)。引数はPrint<List<Person>>(List<Person> items)と同じであるが、再度、セクション7.4.3.2言語

再帰的、構築タイプは、IF(型引数の同じ番号を持つ)別の構築型より特異的であると分解能を提供します少なくとも1つの型引数はより具体的であり、型引数は他の型引数に対応する型引数より具体的ではありません。

ので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

つまり、Print は、常にTが何でもよいので見ている最高の一致とみなされますか?しかし、あなたがPrint (List items)メソッドを追加すると、それは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

関連する問題