views:

561

answers:

11

Hello everyone,

I realize this is a pretty open question and could get a variety of answers, but here goes.

Using C# (or Java, or any OO language), is there a general rule that states how many variables should be passed into the constructor? The number of variables I am passing into the constructor of the extended classes seem to be getting out of hand.

In an effort to encapsulate the data of a class, I declare the members private, initialize them in my constructor, and use public accessors.

Here is an example:

public class A
{
  private int var1;
  private int var2;
  private int var3;

  //3 variables passed in
  public A(int v1, int v2, int v3)
  {
    var1 = v1;
    var2 = v2;
    var3 = v3;
  }

  //Properties (accessors) here
}

public class B : A
{
  private int var4;
  private int var5;

  //5 variables passed in
  public B(int v1, int v2, int v3, int v4, int v5)
  : base(v1,v2,v3)
  {
    var4 = v4;
    var5 = v5;
  }

  //Properties (accessors) here
}

public class C : B
{
  private int var6;
  private int var7;

  //7 variables passed in !!!
  public C(int v1, int v2, int v3, int v4, int v5, int v6, int v7)
  : base(v1,v2,v3,v4,v5)
  {
    var6 = v6;
    var7 = v7;
  }

  //Properties (accessors) here
}

My constructors are usually passing in different objects, not just ints. I started questioning my design when I started passing in 7 variables to the constructor of the child class, but I have also had trouble figuring out a different way to do this.

Is this considered bad programming practice? Is there a general limit to the number of variables you should pass into a constructor?

+11  A: 

Generally I've found if there's more than 3, that's a sign to do a quick sanity check on the design. If there's more than 5, that's a major warning that something is probably wrong with the design.

However, note the word "probably" - in the end, the only real rule is use as many as needed, no more and no less. There are always exceptions and cases where more parameters makes the most sense.

If the parameters are related somehow, you should encapsulate them into a container class.

If the parameters are not related - e.g. it makes no sense to group them into a container class - your class is probably doing too many things. There's generally no reason a single class should be aware of 7 totally disparate pieces of information. Break your class apart into separate classes. It might make sense to delegate parameters 3 and 4 to a subclass and 5, 6 and 7 to another class for example - and your parent class simply coordinates the operations between them.

Rex M
+1'ed for sanity check.
Jarrett Meyer
+3  A: 

Its difficult to put a hard, fast number to what is "too much". The real question is this: What is your class doing? Is the class doing too much? If so, it is time to break the class into smaller, more concise classes.

Constructor parameters should include as many as necessary to define the dependencies/inputs for the class. If the class is reduced to have one job in life, then your constructor parameters will probably be correct.

Brian Genisio
+25  A: 

For me, the correct answer is:

You should pass in as many variables as is required to setup the object in a state that is not invalid.

Anything else that is "option", I prefer to leave as properties, especially now that C# provides object initializers.

Reed Copsey
Amen, just make sure the constructed object is valid.
csharptest.net
Pish. Someone else always says it first.
Mark
No more than 3, and no less than 7 :D
sixlettervariables
+1, though IME the only time I've ever needed to pass more than around 7 was when I was writing and using an 8-item Tuple<> class in C#. And even then I wound up refactoring it.
chsh
I agree - in general, I think that constructors needing more than 2-3 arguments are usually a sign that a class has gotten too big, and should be refactored into smaller parts. I have had a couple of instances where many parameters were required, but it's a rare, fringe case.
Reed Copsey
A: 

Especially since the newer features that allow you to set variables in a block with the instantiation, I tend to only use parameters on creation for things that HAVE to be set when the class is created, in which case I make the basic constructor private or protected.

For example, if you had a class Rectangle, it might make sense to make the constructor Rectangle(double width, double height), and make the Rectangle() constructor private.

Russell Steen
A: 

Also, you might put a parameterless private constructor, if you believe that your class should only set it's properties values through the constructor.

devoured elysium
A: 

As others have said, there is no hard rule on this, it really depends. However, there is concrete evidence as to how many things a person's brain can grasp at once: that's the 7 + or - 2 rule.

This type of question is very well answered in Code Complete by Steve McConnell. I recommend you read this book if you haven't already.

JRL
A: 

A system has too many parameters as soon as it becomes hard to remember how to use them. If they are all ints, 3 is too many. If they are different types you can have more.

This is a smell in Martin Fowler's Refactoring book. This web page contains links to standard refactorings that help.

In your case, you might want to consider a builder object (where you can gradually add the parameters and the builder figures out the class) or a parameter object.

Kathy Van Stone
+1  A: 

One thing I love about the 3.5 framework...

new Foo {
    Street = "909 Rose Ave",
    City = "San Diego",
    State = "CA",
    FName = "Joe",
    LName = "Wazowski",
    ID = "987665454"
};

No more worrying about too many constructors, or too many constructors with too many parameters.

Jagd
+1 I wish they'd let methods be called in a similar way - this is so much more readable than `int i = GetSomething(true, false, "Bob", 42)`
MusiGenesis
To MusicGensis: C# 4.0 will allow you to do this. `Foo(i: 5, someString: "foobar");`
JulianR
You don't need the .NET 3.5 to use object initializes, you can use them (and most features of C# 3.0) in .NET 2.0 projects as well.
Allon Guralnek
+1  A: 

My personal rule of thumb is 5

If you need more, wrap them in a structure or object.

This changes when you do not have to initialize the object. If I initialize an object using a IOC container the number of constructure parameters are basically unlimited.

Dejan
A: 

IMHO, using TDD is a helpful perspective to evaluate this problem. Once your ctor is hard to apply to the unit test ctor or SetUp(), the arguments of initialization/factory are too many and relatively too tightly coupled.

Mike Jiang
A: 

You need to pass in everything required to construct the class. What i often do when i find myself passing in a lot of variables is make a "Configuration" class for the object that holds the information needed to construct the it, passing that to the constructor. It greatly simplies instantiating objects and makes for a cleaner design.

Josh