For exact rules, see the overload resolution specification . But in short, this happens as follows.
First create a list of all available 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 )
Then eliminate any inappropriate constructors. An applicable constructor is one where each formal parameter has a corresponding argument, and the argument is implicitly converted to the formal parameter type. Assuming Point is a value type, we exclude versions of "int" and "Point". It 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 one who has "params" in its expanded or unexpanded form is applicable. In this case, this applies in both forms. When this happens, we discard the expanded form. So the leaves
public EffectOptions ( object[] options ) public EffectOptions ( IEnumerable<object> options ) public EffectOptions ( string name ) public EffectOptions ( object owner )
Now we must determine the best candidates. Bestselling rules are complex, but the short version is more specific than less specific . A giraffe is more specific than a mammal, a mammal is more specific than an animal, an animal is more specific than an 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 (you see why?), So it can also be fixed. It leaves
public EffectOptions ( object[] options ) public EffectOptions ( string name )
And now we are stuck. object [] is no more or less specific than a string. Therefore, this gives an ambiguity error.
This is just a brief sketch; the real tiebreaking algorithm is much more complicated. But these are the basics.