user1306322
user1306322

Reputation: 8721

Reducing number of very long constructor overloads with just a few different parameters

I made custom interface system which uses basic UI controls like button, label, etc. Some controls have many options, so they use long constructors, and they only differ in one or two parameters. And this is work in progress, so I change optional parameters a lot, and it takes quite some time to apply changes to all constructors.

public Button(string Text, Rectangle Rect, Texture2D Texture, bool moreStuff)
public Button(string Text, Point Position, Texture2D Texture, bool moreStuff)
public Button(string Text, Vector2 Position, Texture2D Texture, bool moreStuff)

I tried using dynamic keyword instead of Rectangle, Point and Vector2 to decrease the number of constructors, and it compiles, works, and seems ok for the moment. But maybe I'm missing something that might break this approach later?

To find out what was passed as dynamic Position I check for .GetType().Name, use a switch and throw an exception at default: if it wasn't a recognized type.

Is it fine to do it like this, or is there a better (more safe or appropriate) way?


Currently it's possible to create a fully customized instance of Button inline, and I wouldn't like to lose that ability.

Upvotes: 1

Views: 416

Answers (5)

Umar Farooq Khawaja
Umar Farooq Khawaja

Reputation: 3987

If you use object initialisers, then you can set each individual property you require independently. You just have to be careful that the various properties can be initialised independently.

For example:

public class Button
{
    public int Width
    {
        get
        {
            return Rectangle.Width;
        }
        set
        {
            Rectangle.Width = value;
        }
    }

    public int Height
    {
        get
        {
            return Rectangle.Height;
        }
        set
        {
            Rectangle.Height = value;
        }
    }

    public int X
    {
        get
        {
            return Rectangle.Left;
        }
        set
        {
            Rectangle.Left = value;
        }
    }

    public int Y
    {
        get
        {
            return Rectangle.Top;
        }
        set
        {
            Rectangle.Top = value;
        }
    }

    public Rectangle Rectangle
    {
        get;
        set;
    }
}

If you had a class like the above, you can do either:

var button = new Button
{
    Rectangle = new Rectangle(...)
}

or:

var button = new Button
{
    Left = 0,
    Top = 0,
    Width = 100,
    Height = 20
}

Object initializer notation is ideal for initializing object via their properties where you can have multiple combinations of properties needing to be set.

Upvotes: 0

Simon Whitehead
Simon Whitehead

Reputation: 65087

Another approach is to type this yourself:

class YourPositioningType {
    public int X { get; set; }
    public int Y { get; set; }

    public static YourPositioningType FromVector(Vector2 vector) {
        return new YourPositioningType() { X = vector.X, Y = vector.Y };
    }

    public static YourPositioningType FromRectangle(Rectangle rect) {
        // etc..
    }
}

Static methods to convert from each of the above types. Then you would call it as:

Button b = new Button("Blah", YourPositioningType.FromVector(new Vector2() { /* etc */));

Then you just use the above class in a single constructor.

Upvotes: 0

User 12345678
User 12345678

Reputation: 7804

You don't need to define constructor arguments if you're finding it tedious. You could use an object initializer quite nicely:

SomeButton button = new SomeButton()
{
    Text = "",
    MoreStuff = false
};

Upvotes: 3

Moha Dehghan
Moha Dehghan

Reputation: 18463

Using dynamic is not appropritate in your scenario. Having differenct constructor overloads is not a bad thing (not worth than abusing the dynamic keyword). Many classes in .NET Framework BCL has several constructor overloads (for example, FileStream class has 15 contstructors) and some methods has several overload for differenct uses (MessageBox.Show for example).

Upvotes: 0

Daniel Hilgarth
Daniel Hilgarth

Reputation: 174329

This calls for a parameter object. That's a class with a property per parameter. Your Button constructor would now only take one parameter: That parameter object.

Using dynamic to reduce the number of overloads is definitely not the correct approach.

Upvotes: 1

Related Questions