在下面的代码中,我定义了两个名为Bar
. 在Foo()
中,我对 进行了三次调用Bar
,并在第三次调用时出错。
前两个解决了预期的重载。然而,第三个产生了以下错误:
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'.
显然,第三个调用绑定到“Bar()”,但未能将第一个参数转换为异常。同样清楚的是,第二个参数是一个字符串,它正在抛出编译器。当它不是字符串时(案例 2),分辨率很好。但是(对我来说)失败的行应该绑定到“Bar()”似乎很明显(因为第一个参数明确地是一个字符串)。
谁能解释为什么编译器使用这个绑定?我会考虑创造性的解决方法,但我真正想要的是解释为什么会发生这种情况。我花了一些时间研究 C# 语言规范,但未能找到(即放弃)明确的答案。显然,我可以重命名其中一种Bar
方法,或提供命名参数,或标记其中一个参数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!
}