0

I'm just wondering if there's an automated way to generate constructors with every possible combination of the parameters you might need.

I have a ctor with 4 parameters, but I want to provide overloads where a developer could pass in a single param, or two or three. By hand I've been writing every possible combination and passing defaults to the 4 parameter one. I also need to then introduce two more "full" prototypes ( with a fifth ), then create all the possible combinations for those as well, so I need loads of ctor overloads to cover all combinations.

I'd like to manually write the three full ctors, then be able to generate the combinations with a context menu click. I haven't seen an option like this in Resharper. Anyone know if there's an existing solution out there already?

6
  • 2
    It really looks like a design issue, having that much constructor is a bad smell. I think the Builder pattern could simplify your code a lot, or at the very least a Factory. But your example really sounds like a Builder. Commented Oct 19, 2015 at 23:26
  • I agree with @Pierre-LucPineault, pick what you believe the object needs to be constructed, if there are pieces that aren't needed in certain situations, maybe you are better off refactoring into separate classes and using inheritance or composition instead of stuffing too much into one class. Commented Oct 19, 2015 at 23:28
  • @Pierre-LucPineault, Ron - what about business-object type classes with properties for which sane defaults exist? The OP might have a valid use-case. Commented Oct 19, 2015 at 23:29
  • 1
    @ValAkkapeddi Its still code smell because there lies the possibility that its incorrectly constructed. Its a "well if this parameter is needed, then we should give them this one, but it has a default value in case they don't need it" situation. If it has sane defaults, it doesn't need to be in the constructor, it can be set after the object is created. Commented Oct 19, 2015 at 23:33
  • @RonBeyer I think it's an over-generalization to call it a code-smell. I'd tend to agree with you in cases where certain 'valid states' exist for an object - it should be guarded either by builder methods or constructors such that you can only ever create a valid instance. However, I think there are several cases where you don't necessarily need this. For instance, 'monster' objects in a game that might be armed with magic items and weapons, but not necessarily so. Commented Oct 19, 2015 at 23:38

3 Answers 3

2

If you need a lot of constructor parameters, rather than struggling with the explosion of possible permutations, consider creating an "options" class that has sensible defaults:

public class FooOptions
{
    public FooOptions()
    {
        MaintenanceInterval = TimeSpan.FromSeconds(30);
        MaximumIdleTime = TimeSpan.FromMinutes(5);
    }
    public TimeSpan MaintenanceInterval { get; set; }
    public TimeSpan MaximumIdleTime { get; set; }
    //etc...
}

then

class Foo
{
    public Foo():this(new FooOptions())
    {
    }
    public Foo(FooOptions opts)
    {
        //...
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, yeah looking at it I think this may be a good way to go. Basically of the five params 3 are always required, so I'll put the two optional ones in an Options class.
2

This situation would be a perfect fit for the Builder pattern.

For example, if the class Foo can have any combination of a String, an int and a Bar:

public class Foo
{
    public string MyString { get; set; }
    public int MyInt { get; set; }
    public Bar MyBar { get; set; }
}

Instead of adding a constructor with every possibility, make a Builder. Here's an example of a simple fluent implementation:

public class FooBuilder
{
    private Foo foo = new Foo();

    public FooBuilder WithString(String someString)
    {
        foo.MyString = someString;
        return this;
    }

    public FooBuilder WithInt(int someInt)
    {
        foo.MyInt = someInt;
        return this;
    }

    public FooBuilder WithBar(Bar someBar)
    {
        foo.MyBar = someBar;
        return this;
    }

    public Foo Build()
    {
        return foo;
    }
}

which can be used like this:

Foo foo = new FooBuilder().WithString("abc").WithInt(3).Build();

This eliminates completely the need for an exponential number of constructors.

Comments

1

Don't need multiple constructor overloads - try using optional/default parameters. Relevant link: https://msdn.microsoft.com/en-us/library/dd264739.aspx

Example code:

class Program
{
    static void Main(string[] args)
    {
        var defaultMonster = new Monster();
        var archerMonster = new Monster("crossbow");
        var knightMonster = new Monster("broadsword", "plate mail");
        var wizardMonster = new Monster(armor: "wizard robe", magicItem: "wand");

        Console.WriteLine(defaultMonster);
        Console.WriteLine(archerMonster);
        Console.WriteLine(knightMonster);
        Console.WriteLine(wizardMonster);
    }
}

class Monster
{
    private readonly string _weapon;
    private readonly string _armor;
    private readonly string _magicItem;

    public Monster(string weapon = "scimitar", string armor = "leather", string magicItem = "nothing")
    {
        _weapon = weapon;
        _armor = armor;
        _magicItem = magicItem;
    }

    public override string ToString()
    {
        return string.Format("Monster armed with {0}, wearing {1}, carrying {2}", _weapon, _armor, _magicItem);
    }
}

1 Comment

Please update your answer with more information and some sample code. Link might stop working

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.