方法重载决策系统如何决定在传递空值时调用哪个方法?

Joa*_*nge 35 .net c# overload-resolution

所以例如你有一个类似的类型:

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 ) {}

}
Run Code Online (Sandbox Code Playgroud)

这里我只使用构造函数给出示例,但如果它们是类型本身的非构造方法,结果将是相同的,对吧?

所以当你这样做时:

EffectOptions options = new EffectOptions (null);
Run Code Online (Sandbox Code Playgroud)

会调用哪个构造函数,为什么?

我可以自己测试一下,但我想了解重载分辨率系统是如何工作的(不确定它是否被称为).

Eri*_*ert 79

有关确切的规则,请参阅重载决策规范.但简而言之,就是这样.

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

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 )
Run Code Online (Sandbox Code Playgroud)

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

public EffectOptions ( params object[] options )
public EffectOptions ( IEnumerable<object> options ) 
public EffectOptions ( string name )
public EffectOptions ( object owner ) 
Run Code Online (Sandbox Code Playgroud)

现在,我们必须考虑具有"参数"的那个是否适用于其扩展或未扩展形式.在这种情况下,它适用于两种形式.当发生这种情况时,我们会丢弃扩展的表单.离开了

public EffectOptions ( object[] options )
public EffectOptions ( IEnumerable<object> options ) 
public EffectOptions ( string name )
public EffectOptions ( object owner ) 
Run Code Online (Sandbox Code Playgroud)

现在我们必须确定适合的候选人.最佳规则是复杂的,但简短版本是更具体的优于不太具体的.长颈鹿比哺乳动物更具特异性,哺乳动物比动物更具特异性,动物比对象更具体.

"对象"版本不是特定于所有版本,因此可以将其删除.该object版本比不太具体IEnumerable<object>的版本(你知道为什么吗?),所以它也可以被消除.离开了

public EffectOptions ( object[] options )
public EffectOptions ( string name )
Run Code Online (Sandbox Code Playgroud)

现在我们被困住了.object []既不比string更具特异性.因此,这会产生歧义错误.

这只是一个简短的草图; 真正的tiebreaking算法要复杂得多.但这些都是基础知识.

  • @Joan:每只长颈鹿都是动物,但不是每只动物都是长颈鹿.因此,长颈鹿比动物更具特异性.每个object []都是一个IEnumerable <object>,但不是每个IEnumerable <object>都是一个object [].因此,object []比IEnumerable <object>更具体. (18认同)

Jar*_*Par 8

在这种情况下,C#编译器不会选择任何构造函数,而是会出错.null对于几个可用的构造函数,该值是合法的,并且没有足够的断开逻辑来选择一个,因此它会产生错误.

C#编译器重载决策逻辑是一个复杂的过程,但它的工作原理的简短(并且本质上不完整)概述如下

  • 收集具有给定名称的所有成员
  • 将成员过滤为具有与提供的参数兼容且具有适当可访问性的参数列表的成员
  • 如果其余成员具有多个元素,则使用打破平局逻辑来选择最佳元素

完整的详细信息列在C#语言规范的第7.4节中.而且我相信Eric会很快就会提供更准确的描述:)