Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calling a constructor with default parameters instead of default constructor

Tags:

c#

struct

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;
    }
}
like image 876
InfoMathze Avatar asked Jan 21 '18 20:01

InfoMathze


People also ask

Can I call parameterized constructor from default constructor?

You can't call a default constructor once you've created a constructor that takes arguments. You'll have to create the no argument constructor yourself in order to make a call from the parameterized constructor. Yes, this will work.

Can a constructor be defined with arguments without default constructor?

Note that if a constructor has any arguments that do not have default values, it is not a default constructor. The following example defines a class with one constructor and two default constructors. You can declare default constructors as explicitly defaulted functions or deleted functions.

Can a constructor be defined with default arguments?

It is possible to have a constructor with default arguments.. It means that if the constructor is defined with n parameters, we can invoke it with less than n arguments specified in the call.

How is a default constructor equivalent to a constructor with default arguments?

If no constructors are explicitly declared in the class, a default constructor is provided automatically by the compiler. Can a default constructor contain a default argument? Yes, a constructor can contain default argument with default values for an object.


2 Answers

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.

like image 64
Marc Gravell Avatar answered Oct 10 '22 01:10

Marc Gravell


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.

like image 41
InBetween Avatar answered Oct 10 '22 03:10

InBetween