tags:

views:

416

answers:

4

This might be a stupid question, but is there any common practice for initializing collection properties for a user, so they don't have to new up a new concrete collection before using it in a class?

Are any of these preferred over the other?

Option 1:

public class StringHolderNotInitialized
{
    // Force user to assign an object to MyStrings before using
    public IList<string> MyStrings { get; set; }
}

Option 2:

public class StringHolderInitializedRightAway
{
    // Initialize a default concrete object at construction

    private IList<string> myStrings = new List<string>();

    public IList<string> MyStrings
    {
        get { return myStrings; }
        set { myStrings = value; }
    }
}

Option 3:

public class StringHolderLazyInitialized
{
    private IList<string> myStrings = null;

    public IList<string> MyStrings
    {
        // If user hasn't set a collection, create one now
        // (forces a null check each time, but doesn't create object if it's never used)
        get
        {
            if (myStrings == null)
            {
                myStrings = new List<string>();
            }
            return myStrings;
        }
        set
        {
            myStrings = value;
        }
    }
}

Option 4:

Any other good options for this?

+10  A: 

In this case, I don't see the reason for the lazy loading, so I would go with option 2. If you are creating a ton of these objects, then the number of allocations and GCs that result would be an issue, but that's not something to consider really unless it proves to be a problem later.

Additionally, for things like this, I would typically not allow the assignment of the IList to the class. I would make this read-only. In not controlling the implementation of the IList, you open yourself up to unexpected implementations.

casperOne
Good point, I didn't think about the possibility of unknown IList implementations.
Andy White
Also, in the framework book, it mentions you really shouldn't expose types of IList<T> or List<T>, but instead use an array and use a List internally.
Robert C. Barth
Which framework book are you referring to? It sounds like something I should read!
Andy White
What rationale does that book use? That might make sense for C++, but why would it make sense for C#?
Arafangion
A: 

private IList myStrings = {"hello", "world"};

shahkalpesh
+2  A: 

For Option 1: if you want to force user to initialize something before using your class then best place to force it is in constructor.

For Option 2: If you're not forcing the user then you really have to initialize an empty collection yourself in the constructor/initializer.

For Option 3: Lazy initialization only makes sense if it involves too much work or its a slow/bulky operation.

My vote goes for option 2.

Hasan Khan
+1  A: 

The only real reason for using the lazy loading solution is for an optimization. And the first rule of optimization is "don't optimize unless you've measured" :)

Based on that I would go with the solution least likely to cause an error. In this case that would be solution #2. Setting it in an initializer virtually eliminates the chance of a null ref here. The only way it will occur is if the user explicitly sets it to null.

JaredPar