以下のコードでは、 という名前の 2 つのオーバーロードされたメソッドを定義していますBar
。ではFoo()
、 を 3 回呼び出しましBar
たが、3 回目の呼び出しでエラーが発生しました。
最初の 2 つは、予想されるオーバーロードに解決されます。ただし、3番目は次のエラーを生成しました:
The type 'string' cannot be used as type parameter 'T' in the generic type or method 'Bar<T>(T, string, params object[])'. There is no implicit reference conversion from 'string' to 'System.Exception'.
明らかに 3 番目の呼び出しは "Bar()" にバインドされていますが、最初のパラメーターを例外に変換していません。また、2 番目の引数が文字列であることは、コンパイラをスローしていることも明らかです。文字列でない場合 (ケース 2)、解像度は問題ありません。しかし、失敗した行は "Bar()" にバインドする必要があることは明らかです (最初のパラメーターは明確に文字列であるため)。
コンパイラがこのバインディングを使用している理由を誰か説明できますか? 私は創造的な回避策を検討しますが、私が本当に探しているのは、なぜこれが起こっているのかの説明です. 私は C# 言語仕様に時間を費やしましたが、明確な答えを見つけることができませんでした (つまり、諦めました)。明らかに、Bar
メソッドの名前を変更したり、名前付き引数を指定したり、パラメーターの 1 つをマークしたりできますref
...しかし、これらのいずれも私の特定のシナリオには理想的ではありません。
関連性があるというわけではありませんが、まさにこれを行う Java コードを作成しましたが、コンパイラーには問題がありませんでした。
コード:
public void Bar(string s, params object[] ps) { } // Call this "Bar()"
public void Bar<E>(E e, string s, params object[] ps) where E : Exception { } // Call this "Bar<T>()"
public void Foo()
{
Exception e;
Object o1, o2;
Bar(e, "fmt {0}", o); // Resolves fine, as expected
Bar("fmt {0} {2}", o1, o2); // Also resolves as expected
Bar("fmt {0} {2}", "bar", o1); // Error!
}