Constructor selection for multiple optional parameters of the same type

In the code below, CreateNode calls the first constructor, as explained here (thanks for the link).

public class Node
{
    public Node(Node parent = null, params Node[] children) { }
    public Node(params Node[] children) { }
    public Node CreateNode() => new Node(new Node(), new Node()); }
}

What is the best way to deal with this whilst retaining the cross purpose constructor functionality (it allows for more expressive composition of code eg XElement).

I was thinking maybe temporarily wrap or cast the parent, but that obviously introduces more boilerplate. Not sure if I could somehow leverage the ValueTuple<> syntax to get what i want? Or implicit and explicit operators?!

EDIT

I wanted to create the nodes in a similar fashion to XElement, etc. eg

new Node(new Node(new Node())

however there were cases where I had already created a parent and wanted to pass that into the constructor of its child nodes eg

Node parent = new Node();
new Node(parent, new Node(), new Node());

Obviously the compiler has to chose one, and so I guess I was really asking how to force it to choose the other, so it knows the first argument should be treated as the parent.

Upvotes: 0

Views: 296

Answers (1)

Sweeper
Sweeper

Reputation: 271040

Right now you are passing the parameter array in its "expanded form", which causes this rule to apply, making both methods an applicable function member.

If a function member that includes a parameter array is not applicable in its normal form, the function member may instead be applicable in its expanded form:

  • The expanded form is constructed by replacing the parameter array in the function member declaration with zero or more value parameters of the element type of the parameter array such that the number of arguments in the argument list A matches the total number of parameters. [...]

And then the rules in better function member decide that the first one is a better function member. Specifically, this one:

Otherwise, if Mp has more declared parameters than Mq, then Mp is better than Mq. This can occur if both methods have params arrays and are applicable only in their expanded forms.

So to solve this problem, just pass your parameter in its "normal form", i.e. as an array. It's not that much more keystrokes if you use an implicitly typed array.

new Node(new[] { new Node(), new Node() })

This way, only one overload is an applicable function member.

Upvotes: 1

Related Questions