c# - 带有参数数组的通用 C# 方法重载解析

标签 c# generics overloading

在下面的代码中,我定义了两个名为 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'.

很明显,第三个调用绑定(bind)到“Bar()”,但未能将第一个参数转换为异常。同样清楚的是,第二个参数是一个字符串,它会丢弃编译器。当它不是字符串时(情况 2),分辨率就可以了。但显然(对我而言)失败的行应该绑定(bind)到“Bar()”(因为第一个参数明确地是一个字符串)。

谁能解释为什么编译器使用这个绑定(bind)?我会考虑创造性的解决方法,但我真正想要的是解释为什么会发生这种情况。我花了一些时间研究 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!
}

最佳答案

答案是重载匹配不考虑约束。至于这是否在 C# 规范中,我不完全确定。匹配总是使用最具体的选项,而 string as generic T 总是比 string as Object 更具体(因为它匹配实际类型而不是子类型)。参见 Constraints are not part of the signature在 Eric Lippert 的博客上。

要实现此功能,如果需要异常约束,请尽可能使用 void Bar(Exception E, ...)

关于c# - 带有参数数组的通用 C# 方法重载解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10627971/

相关文章:

c# - Asp.net MVC Bundle 能否在 CSS 中改造 LESS?

c# - 选择一个*启发式函数

c# - 如何创建不比较两个单独继承类的抽象基类 IComparable?

PHP 间接修改重载属性 - 使用 ARRAYS

java - 在 ProGuard for Android 中禁用主动重载

java - 将 java 转换为 scala 代码 - 更改方法签名

c# - AspNetCore 中的版本冲突

c# - 关于构建分布式应用程序的建议?

Java 错误 : New Generic TreeNode Array

generics - 在构造函数中使用模板类