当传递空值时,方法重载解析系统如何决定调用哪个方法?

发布于 2024-10-19 18:03:22 字数 605 浏览 1 评论 0原文

例如,您有一个类似的类型:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

风向决定发型 2024-10-26 18:03:22

有关确切规则,请参阅 重载解析规范。但简单来说,事情是这样的。

首先,列出所有可访问构造函数。

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 )

接下来,消除所有不适用构造函数。适用的构造函数是每个形式参数都有相应的参数,并且参数可以隐式转换为形式参数类型的构造函数。假设 Point 是值类型,我们消除“int”和“Point”版本。现在

public EffectOptions ( params object[] options )
public EffectOptions ( IEnumerable<object> options ) 
public EffectOptions ( string name )
public EffectOptions ( object owner ) 

,我们必须考虑带有“params”的参数是否适用于其扩展未扩展形式。在这种情况下,这两种形式都适用。当这种情况发生时,我们会丢弃扩展形式。因此,

public EffectOptions ( object[] options )
public EffectOptions ( IEnumerable<object> options ) 
public EffectOptions ( string name )
public EffectOptions ( object owner ) 

现在我们必须确定适用候选人中的最佳。最佳规则很复杂,但简短的版本是更具体比不太具体更好。长颈鹿比哺乳动物更具体,哺乳动物比动物更具体,动物比物体更具体。

object 版本不如所有版本具体,因此可以将其删除。 IEnumerable版本不如 object[] 版本具体(您明白为什么吗?),因此它也可以被消除。现在

public EffectOptions ( object[] options )
public EffectOptions ( string name )

我们陷入困境了。 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.

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 )

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

public EffectOptions ( params object[] options )
public EffectOptions ( IEnumerable<object> options ) 
public EffectOptions ( string name )
public EffectOptions ( object owner ) 

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

public EffectOptions ( object[] options )
public EffectOptions ( IEnumerable<object> options ) 
public EffectOptions ( string name )
public EffectOptions ( object owner ) 

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. The IEnumerable<object> version is less specific than the object[] version (do you see why?) so it can be eliminated too. That leaves

public EffectOptions ( object[] options )
public EffectOptions ( string name )

And now we are stuck. object[] is neither more nor less specific than string. 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.

ㄖ落Θ余辉 2024-10-26 18:03:22

在这种情况下,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

  • Collect all members with the given Name
  • Filter the members to those with parameter lists that are compatible with the provided arguments and with the appropriate accessibility
  • If the remaining members has more than one element, employ tie breaking logic to choose the best of them

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 :)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文