5

私は、過負荷解決で奇妙な動作に気付きました。オーバーロード、ジェネリック型推論と 'params'キーワード

は、私は次のメソッドを持っていると仮定します。

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

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

さて、私は、このオーバーロードを追加便宜上ように、この方法は、多くの場合、明示的な引数の数が少ないと呼ばれることを知っている:

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

    // For debugging 
    Console.WriteLine("DoSomething<T>(params 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>です。 2番目の数字はList<string>IEnumerable<string>です。最初の変換は、7.4.3.4の規則で2番目の変換よりも優れています。

反直観ビットは型推論です。あなたが式の外にそれを取る場合は、それが期待どおり、それは動作します。その時点で

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

、各呼び出しで唯一の適用可能な機能のメンバーがあります。

+0

ありがとう、ジョンそれは私が必要とした正確な説明です。私が望むように動作させるための回避策はありますか?そうでない場合は別の名前を使用する必要があると思います... –

+0

はい、ジェネリック型のパラメータを明示的に指定すると動作することに気付きました。しかし、私は型推論の利点を失う... –

+4

わかりやすくするために、別の名前を使うことをお勧めします - あるいは、複数の項目でのみ使うつもりなら、 '(T first、params T [] others) ' –

関連する問題