ChrisJ
ChrisJ

Reputation: 5241

C#: same-signature methods/constructors and named arguments

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

Answers (3)

linuxuser27
linuxuser27

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

Jonathan Nixon
Jonathan Nixon

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

Hertzel Guinness
Hertzel Guinness

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

Related Questions