Reputation: 5241
Suppose for instance I'm defining a Complex
class for representing complex numbers. I would like to define two constructors, so that I can write for example:
Complex z1 = new Complex(x: 4, y: 3);
Complex z2 = new Complex(r: 2, theta: Math.PI / 4);
However, I cannot define the constructors like this:
public Complex(double x, double y) { ... }
public Complex(double r, double theta) { ... }
because both constructors would have the same signature, which is not allowed. But in C# 4 I can write this, using an optional argument:
public Complex(double x, double y) { ... }
public Complex(double r, double theta, bool unused=true) { ... }
It works, I can then use the above constructor calls as intended. The sole purpose of the unused
argument is to make the signatures different; it's totally unused, both when defining and when calling the constructor.
To me this seems to be a an ugly trick: is there any better option?
Upvotes: 2
Views: 973
Reputation: 7353
Make the constructor private and have a static factory style function.
public static Complex CreateComplexPolar(double r, double theta);
public static Complex CreateComplex(double x, double y);
You can do validation on the inputs based on what they should be.
Another possibility would be to create a type that encapsulates the inputs and use constructors as you previously mentioned.
public struct PolarCoordinates
{
public double Rho;
public double Theta;
}
public struct CartesianCoordinates
{
public double X;
public double Y;
}
public Complex(PolarCoordinates pc);
public Complex(CartesianCoordinates cc);
Upvotes: 7
Reputation: 4952
The only thing I can think of would be to make one constructor (double, double) and the other could be double, Func.
public Complex(double x, double y) { ... }
public Complex(double r, Func<double> theta) { ... }
It looks like in your example from above that you are doing a calculation and the result of that calculation is the 2nd value for that constructor. If that was always the case then you could just make it a Func parameter instead. Kind of a hack, but it might be better than having an optional 3rd parameter that does nothing.
Upvotes: 0
Reputation: 5940
Create a static method to create the class, say Complex::FromDouble
and Complex::FromDoubleAndTheta
.
You can go one step further and make the real constructor private in order to force that construction.
For example, see TimeSpan's FromDays and FromHours.
p.s. Use better names :)
HTH
Upvotes: 3