C# Constructor overloads: new object.FromOtherObject()?

I have two different types of nodes, I need to be able to convert between them in a relatively easy fashion. I was thinking of doing this in the constructor as it would make code a lot cleaner.

NodeA nodea = new NodeA();

NodeB nodeb = new NodeB.FromNodeA(nodea);

I've been googling for a couple hours and haven't been able to find a way to do this. The best solution I've come up with is;

public NodeB() { }

public static NodeB FromNodeA(NodeA theNodeA)
{
    NodeB b = new NodeB();
    b.Value = theNodeA.value;
    // etc..
}

But this makes code look a little more funky like so;

NodeB b = NodeB.FromNodeA(nodea);

Ideally I'd like to be able to do this:

NodeB b = new NodeB().FromNodeA(nodea);

Edit; Or is the static method I've already done the more (traditionally) correct way of accomplishing this?

Jon Skeet
people
quotationmark

You could just have a constructor with a NodeA parameter:

NodeB nodeB = new NodeB(nodeA);

... but having a factory method is also a pretty idiomatic solution. It has various benefits, including being able to have multiple methods with different names but the same parameter types - e.g.

TimeSpan.FromSeconds(...)
TimeSpan.FromMinutes(...)

It also allows the method more flexibility:

  • It could return null in some cases (e.g. for null input)
  • It could return a reference to an existing object
  • It could return an instance of a subclass (e.g. Encoding.GetEncoding)
  • You can convert the method group to a delegate, which is handy for LINQ operations (no need for a lambda expression)

One upside of making it a constructor is that if you have a subclass of NodeB, that could have a constructor which also takes a NodeA and chains to the NodeB(NodeA) constructor. It's hard to achieve the same thing using the factory method approach without code duplication.

And as per Alessandro's comment, you could have a user-defined conversion operator, either explicit or implicit. I would be very careful with implicit conversions though - they can feel like a great idea at the time, but end up leading to code which is unclear later.

Finally, you could also have a ToNodeB() method on NodeA instead - either implemented directly, or as an extension method.

So to round it all up, here are the options for how the "user code" might look:

NodeA nodeA = ...;
// One of...
NodeB nodeB = nodeA;                  // Implicit conversion
NodeB nodeB = (NodeB) nodeA;          // Explicit conversion
NodeB nodeB = new NodeB(nodeA);       // Constructor
NodeB nodeB = NodeB.FromNodeA(nodeA); // Factory method
NodeB nodeB = nodeA.ToNodeB();        // Instance or extension method on NodeA

people

See more on this question at Stackoverflow