例如,您有类似的类型:
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);
将调用哪个构造函数,为什么?
我可以自己测试一下,但我想了解重载分辨率系统是如何工作的(不确定这是否就是它的名称)。
答案 0 :(得分:76)
有关具体规则,请参阅the overload resolution spec。但简而言之,就是这样。
首先,列出所有可访问的构造函数。
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>
版本的特定性不如object[]
版本(您知道为什么?)因此也可以将其删除。离开
public EffectOptions ( object[] options )
public EffectOptions ( string name )
现在我们被困住了。 object[]
并不比string
更具特异性。因此,这会产生歧义错误。
这只是一个简短的草图;真正的tiebreaking算法要复杂得多。但这些都是基础。
答案 1 :(得分:7)
在这种情况下,C#编译器不会选择任何构造函数,而是会出错。值null
对于几个可用的构造函数是合法的,并且没有足够的打破平局逻辑来选择一个因此它产生错误。
C#编译器重载决策逻辑是一个复杂的过程,但对其工作方式的简短(并且本质上不完整)概述如下
完整的详细信息在C#语言规范的第7.4节中列出。而且我确信埃里克很快就会提供更准确的描述:)