【问题标题】:Generic C# method overload resolution with parameter array带有参数数组的通用 C# 方法重载解析
【发布时间】:2012-05-17 21:06:40
【问题描述】:

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

【问题讨论】:

  • 但是这个问题处理的是模棱两可的问题。在这种情况下,编译器和我都同意存在绑定,我们只是不同意哪一个!

标签: c# generics overloading


【解决方案1】:

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

为了使这项工作,如果需要异常约束,请尽可能使用void Bar(Exception E, ...)

【讨论】:

  • 忽略约束很有趣。但是第一个参数是一个字符串不是使非泛型更好的匹配吗?我的意思是,它绑定到一个导致失败的方法,而不是一个不会失败的方法。你知道吗?
  • 由于第一个Bar的第二个参数是可选对象,匹配第二个更具体。 Bar(string as T, string, ...)Bar(string, string as Object, ...) 更具体。我想你可以换一种方式考虑,但是编译器团队是用第一种方式写的。 Eric Lippert (blogs.msdn.com/b/ericlippert) 可能对这种情况有话要说。带走的,作为T 的字符串比作为Object 的字符串更具体。
  • 那篇博文很棒。评论区真的火了!我需要一些时间来消化它,但这是一个巨大的帮助。谢谢@climbage 和特拉维斯。
【解决方案2】:

Bar("fmt {0} {2}", "bar", o1); // 错误! 通过特异性优先级,它查找第二个参数是字符串(字符串比对象更具体)的方法签名,然后尝试解析类型参数,但它不能。为了说明这一点,尝试将第三个调用替换为:

Bar("fmt {0} {2}", (object)"bar", o1); // Now it is fine for compiler!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多