views:

150

answers:

4

For a class instance to work properly, some fields should be properly initialized, what's your strategy to initialize these field, what should be given through constructor, what should be given through property?

My confusion is that, if the constructor requires a long parameter list, it's hard to use, if through properties, i tend to forget to set some properties.

What's the best practice?

+2  A: 

This is always a balancing act - you don't want to have constructors that require many parameters but you also don't want to require that a user set many properties before an object is in a valid state. Unfortunately there is no real guidance here as you must use your best judgment for the situation at hand.

Many times you may need to create a composite type which has many properties and many possible configurations (e.g. System.Web.Page). Composite types tend to have simple constructors that take little or no parameters and all values must be set through properties. Composite types are high-level types that are composed of lower-level factored (or primitive) types.

Factored types tend to be simpler, contain less state, and can be completely initialized via their constructors. Examples of factored types are System.String and System.Int32. These types are very simple and tend to be the building blocks of composite types.

If your type is a factored type then try your best to allow consumers to initialize the type completely via the constructor. If your type is a composite type then it is better to offer simple constructors with little or no parameters and require that the consumer configure the instance via property setters.

Andrew Hare
+1. I will point out that in the case of `composite types`, you'll want to have a well-defined contract defined which determines which properties must be set in order to give the instance its state. Document the hell out of it. That way, a year down the road, the object doesn't get horribly miss-configured :)
Kivin
@Kivin - Absolutely!
Andrew Hare
+1  A: 

Now that .NET 3.5 allows you set any property on creation, I generally restrict any constructor with parameters to situations where the instance absolutely must have a value on creation. There really isn't any other reason to add constructor overloads with parameters IMO.

Thomas
+1  A: 

I think the best thing would be to perform validation and generally try to keep constructors with no parameters as it is often a requirement for different .NET libraries.

With validation you will have to check the object's validity, but it is pretty common thing to do. Something among the lines:

public interface IValidateable {
  IEnumerable<string> Validate();
}

public class Person : IValidateable {
    public string Title { get; set; }
    public string First { get; set; }
    public string Last { get; set; }
    public Address HomeAddress { get; set; }

    public Person() {
      HomeAddress = new Address();
    }


    public IEnumerable<string> Validate() {
      var errors = new List<string>();
      if (string.IsNullOrEmpty(First))
        errors.Add("First name is required.");
      // And so on...
      return errors;
    }    
}

// Usage
var p1 = new Person();
var p2 = new Person {
    First = "Dmitriy"
  };

if (p1.Validate().Any()) {
  // Do something with invalid object
}
Dmytrii Nagirniak
what if the class is not a business class, maybe i should go for checking and raising exceptions.
Benny
Yes, it is another option.
Dmytrii Nagirniak
+2  A: 

You must ask yourself, if your class needs that many things to be created, perhaps it is doing too much. It's a sign that you should reconsider your design, or just how much "work" the constructor is doing.

It is true that you should not be able to create an instance with invalid state; thus the constructor should take all properties you need to be in a valid state.

To a degree, it depends on your model. For example, the ORM I use has the constructor take one parameter; an ID by which it can load all the other properties. It would be annoying if I had to pass them all in (that's the job of the ORM really; to set this object up). So in that sense, you can argue you have an "invalid" object (no properties set). But you'd be wrong; what you actually have is a "blank" or "empty" object. That's not the same as invalid.

So think carefully about what it means for your object to be "invalid". I would consider it invalid if other methods took this object, and threw an exception because something wasn't set. Use this logic to determine what needs to be in the constructor, and what can be set later (by some other process).

Noon Silk