6

I want to call a constructor of a struct, that has default values for all parameters. But when I call the parameterless constructor of MyRectangle a not defined constructor get's called. Why is that? Is it possible to not have a not from me created constructor called?

using System;

namespace UebungClasses
{
    class Program
    {
        static void Main(string[] args)
        {
            MyRectangle sixRec = new MyRectangle(3, 2);
            MyRectangle oneRec = new MyRectangle();

            Console.WriteLine("area of six: " + sixRec.Area() + " area of one: " + oneRec.Area());
        }
    }

    public struct MyRectangle
    { 
        public MyRectangle(double w = 1, double l = 1)
        {
            width = w;
            length = l;
            Console.WriteLine("Width: " + width + " Lenght: " + length);
        }

        public double Area()
        {
            return width * length;
        }

        private double width;
        private double length;
    }
}
2
  • If MyRectangle had been a class instead of a struct, it would have worked the way you intended. But for historical reasons, any use of new T() where T is a value type, works the same as default(T). Commented Jan 21, 2018 at 23:16
  • Did you try declaring the parameterless constructor private, such as « private MyRectangle() {} » Commented Aug 25, 2020 at 16:40

2 Answers 2

5

No, basically. If you use new MyRectangle(), it will always prefer the default constructor (meaning: zero init in the case of struct).

If you were dealing with integers, one potential workaround would be to use xor with your desired default in the property accessors - this would mean that when the fields are zero, you get the default values from the accessors. Unfortunately, to do this with double would require using unsafe code to reinterpret the types.

One other potential solution would be to add a dummy parameter that you can use, for example:

new MyRectangle(dummy: true)

This dummy parameter would do literally nothing except allow you to select the custom constructor.

Another final option would be to use a factory method (static MyRectangle Create(...)) instead of the constructor.

Sign up to request clarification or add additional context in comments.

9 Comments

Wouldn't you consider a isNotDefault flag a viable choice? You'd pay a small penalty on any property access but if its not a problem, its a rather clean way to get custom "default" value behavior in structs.
@InBetween given the choice, I'd prefer the xor approach - an xor is a simple bit-op that pipelines nicely into a CPU chain and will usually out-perform something that relies on a branch
I agree, I was referring to the general case where integers are not involved.
Sad, that i can't do that the way I wanted, but hey, at least I learned something new! Thank You.
@InBetween I might be entirely too happy to use unsafe code - that would barely slow me down :)
|
1

The issue here is that the compiler will always resolve first to a valid constructor with no default parameters. Its a bit like with generics, where the non generic overload wins, well here, the non default parameter overload is preferred.

Because structs all have a parameterless constructor, that one will be chosen over yours.

A way around this if you need a different default rectangle could be:

public struct MyRectangle
{
    private readonly bool isNotDefault;

    public MyRectangle(double w, double l)
    {
        isNotDefault = true;
        width = w;
        length = l;
    }

    public double Area()
    {
        //Notice the use of the properties,
        //not the backing fields.
        return Width * Length;             
    }

    private readonly double width, length;
    public double Width => isNotDefault ? width: 1;
    public double Length => isNotDefault ? length : 1;

    public override string ToString()
        => $"Width: {Width} Lenght: {Length}";
}

Not sure I'd recommend this for a rectangle, after all a zero sized rectangle seems a reasonable choice, but there are cases where the default value really doesn't make sense. A clear example is a struct representing a rational number, where the default value is a mathematical indetermination: 0/0.

1 Comment

Yes, sure a default of 0 / 0 is more fitting, but I wondered and "boild down the code" as SE told me to. Thank You for your answer, but I think I will accept the other one.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.