繁体   English   中英

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

[英]Generic C# method overload resolution with parameter array

在下面的代码中,我定义了两个名为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()”,但是未能将第一个参数转换为Exception。 显然,第二个参数是字符串,它会抛出编译器。 如果它不是字符串(情况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#规范中,我不确定。 匹配始终使用最特定的选项,因为字符串T比字符串T作为Object总是更具体(因为它匹配实际类型而不是子类型)。 请参阅约束不是 Eric Lippert博客上签名的一部分

要进行此工作,如果需要例外约束,请尽可能使用void Bar(Exception E, ...)

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM