5

オーバーロードの解決に関する奇妙な動作に気付きました。

次のメソッドがあるとします。

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");

ただし、どちらの場合も、with のオーバーロードparamsが呼び出されます。IEnumerable<T>a の場合はオーバーロードが呼び出されることを期待していたでしょうList<T>(少なくとも私には)。

この動作は正常ですか? 誰でも説明できますか?MSDNドキュメントでそれに関する明確な情報を見つけることができませんでした...ここに含まれるオーバーロード解決ルールは何ですか?

4

1 に答える 1

9

C# 3.0 仕様のセクション 7.4.3 は、ここで関連するビットです。基本的に、パラメーター配列は展開されているため、比較しています:

public static void DoSomething<T>(T item)

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

T最初の一致の は であると推測されList<string>T2 番目の一致の は であると推測されますstring

ここで、引数からパラメーターの型への変換に関係するものを考えてみましょ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");

その時点で、各呼び出しに適用可能な関数メンバーは 1 つだけです。

于 2009-11-30T15:50:22.653 に答える