当传递空值时,方法重载解析系统如何决定调用哪个方法?
例如,您有一个类似的类型:
public class EffectOptions
{
public EffectOptions ( params object [ ] options ) {}
public EffectOptions ( IEnumerable<object> options ) {}
public EffectOptions ( string name ) {}
public EffectOptions ( object owner ) {}
public EffectOptions ( int count ) {}
public EffectOptions ( Point point ) {}
}
这里我只是给出使用构造函数的示例,但如果它们是类型本身的非构造函数方法,结果将是相同的,对吧?
那么当你这样做时:
EffectOptions options = new EffectOptions (null);
将调用哪个构造函数,为什么?
我可以自己测试一下,但我想了解重载解析系统是如何工作的(不确定这是否就是所谓的)。
So for instance you have a type like:
public class EffectOptions
{
public EffectOptions ( params object [ ] options ) {}
public EffectOptions ( IEnumerable<object> options ) {}
public EffectOptions ( string name ) {}
public EffectOptions ( object owner ) {}
public EffectOptions ( int count ) {}
public EffectOptions ( Point point ) {}
}
Here I just give the example using constructors but the result will be the same if they were non-constructor methods on the type itself, right?
So when you do:
EffectOptions options = new EffectOptions (null);
which constructor would be called, and why?
I could test this myself but I want to understand how the overload resolution system works (not sure if that's what it's called).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
有关确切规则,请参阅 重载解析规范。但简单来说,事情是这样的。
首先,列出所有可访问构造函数。
接下来,消除所有不适用构造函数。适用的构造函数是每个形式参数都有相应的参数,并且参数可以隐式转换为形式参数类型的构造函数。假设 Point 是值类型,我们消除“int”和“Point”版本。现在
,我们必须考虑带有“params”的参数是否适用于其扩展或未扩展形式。在这种情况下,这两种形式都适用。当这种情况发生时,我们会丢弃扩展形式。因此,
现在我们必须确定适用候选人中的最佳。最佳规则很复杂,但简短的版本是更具体比不太具体更好。长颈鹿比哺乳动物更具体,哺乳动物比动物更具体,动物比物体更具体。
object
版本不如所有版本具体,因此可以将其删除。IEnumerable
我们陷入困境了。
object[]
与string
一样具体。因此,这会产生歧义错误。这只是一个简短的草图;真正的决胜算法要复杂得多。但这些是基础知识。
For the exact rules, see the overload resolution spec. But briefly, it goes like this.
First, make a list of all the accessible constructors.
Next, eliminate all the inapplicable constructors. An applicable constructor is one where every formal parameter has a corresponding argument, and the argument is implicitly convertible to the formal parameter type. Assuming that Point is a value type, we eliminate the "int" and "Point" versions. That leaves
Now, we have to consider whether the one with "params" is applicable in its expanded or unexpanded form. In this case it is applicable in both forms. When that happens, we discard the expanded form. So that leaves
Now we must determine the best of the applicable candidates. The bestness rules are complicated, but the short version is that more specific is better than less specific. Giraffe is more specific than Mammal, Mammal is more specific than Animal, Animal is more specific than object.
The
object
version is less specific than all of them, so it can be eliminated. TheIEnumerable<object>
version is less specific than theobject[]
version (do you see why?) so it can be eliminated too. That leavesAnd now we are stuck.
object[]
is neither more nor less specific thanstring
. Therefore this gives an ambiguity error.That is just a brief sketch; the real tiebreaking algorithm is much more complicated. But those are the basics.
在这种情况下,C# 编译器不会选择任何构造函数,而是会出错。值
null
对于多个可用构造函数来说是合法的,并且没有足够的平局打破逻辑来选择一个,因此会产生错误。C# 编译器重载解析逻辑是一个复杂的过程,但对其工作原理的简短(本质上不完整)概述如下:
完整的详细信息列于 C# 语言规范的第 7.4 节中。我相信埃里克很快就会过来给出更准确的描述:)
In this case the C# compiler won't pick any constructor and instead will error. The value
null
is legal for several of the available constructors and there is insufficient tie breaking logic to pick one hence it produces an error.The C# compiler overload resolution logic is a complex process but a short (and inherently incomplete) overview of how it works is as follows
The full details are listed in section 7.4 of the C# language spec. And I'm sure Eric will be along shortly to give a much more accurate description :)