tags:

views:

546

answers:

10

If an object has a property that is a collection, should the object create the collection object or make a consumer check for null? I know the consumer should not assume, just wondering if most people create the collection object if it is never added to.

+1  A: 

I create an empty collection. Sure, it has a slight memory cost, but not a large enough one to be concerned about it.

R. Bemrose
+1  A: 

IMO, this is where IEnumerable comes in nicely.

Personally, I like my 'collection' properties to be initialized to empty lists.

leppie
+3  A: 

This depends on the contract you have between your API and the user.

Personally, I like a contract that makes the Object manage its collections, i.e., instantiating them on creation, and ensuring that they can't be set to null via a setter - possibly by providing methods to manage the collection rather than setting the collection itself.

i.e., addFoo(Foo toAdd) instead of setFooSet(Set set), and so on.

But it's up to you.

JeeBee
+2  A: 

I typically will create the collection then provide methods to add / remove items from the internal collection rather than making the consumer of the class worry about checking for null. This also gives you the ability to control better what happens to the collection. Ultimately it depends on what it is for, but most likely if your class has a collection it isn't just so that the consumer of the class can have a collection of those objects. Otherwise, why would they use your class?

Steven Behnke
+2  A: 

While what I say here is not universal by any means, I think collections are mostly suited as private properties which should be accessed by public methods on the object itself. Therefore, the object is responsible to create and destroy them as needed. This way, it won't be possible to set it to null from external code.

Mehrdad Afshari
+1  A: 

If the collection is an intrinsic part of the object, then the object should generally create it (and not allow the user to set it to a different collection instance).

Eric Rosenberger
+1  A: 

I've tried both ways and I am usually happy when I find I have already instanciated it. Alternatively you could hide the the implementation from the consumer behind a set of methods that can handle the check for you.

Jamal Hansen
+2  A: 

I prefer to create the collection upon instantiation, provide add/remove methods in the containing object, and if needed, provide addAll/removeAll methods for adding and removing entire external collections. I never allow the collection object to be accessed for get or set by the caller - I may, however, provide a getter that returns a copy (poss. immutable) of the collection.

I have also had copy-on-write implementations which provide an immutably wrapped view, since any mutation will create a new underlying collection.

Software Monkey
+6  A: 

You can also use the "Lazy initailizer" pattern where the collection is not initialized until (and unless) someone accesses the property getter for it... This avoids the overhead of creating it in those cases where the parent object is instantiated for some other purpose that does nto require the collection...

   public class Division
    {
        private int divId;
        public int DivisionId { get; set; }

        private Collection<Employee> emps;
        public Collection<Employee> Employees
        { get { return emps ?? (emps = new Collection<Employee>(DivisionId)); } }
    }

EDIT: This implementation pattern is, in general, not thread safe... emps could be read by two different threads as null before first thread finishes modifying it. In this case, it probably does not matter as DivisionId is immutable and although both threads would get different collections, they would both be valid. Whne the second thread fihishes, therefore, emps would be a valid collection. The 'probably' is because it might be possible for the first thread to start using emps before the second thread resets it. That would not be thread-safe. Another slightly more complex implementation from Jon SKeet is thread-safe (see This article on SIngletons for his example/discussion on how to fix this.

Charles Bretana
Happen to like this way...suits my needs..
CSharpAtl
Happens to be my style of doing things too!! Vote+1
Perpetualcoder
OK but (1) be aware that this implementation of lazy initialization is not thread-safe - which is OK as long as its documented as such (2) the dependency of Employees on the read/write property DivisionId means the order of setting properties is significant - contrary to MS guidelines.
Joe
If Division is an entity object, then DivisionId is (should be) immutable, so thread-safe it will be ...
Charles Bretana
are you sure Employees { get; } is atomic?
Jimmy
atomic? 2B thread safe, I thought, any 1of the 4 required race conditions must be false.. 1. Shared mem access fm/mult threads2. Invariant must exist that is assoc w/ shared memory3. The Invariant must be false during portion of process4. thread switch can happen while invariant is false.
Charles Bretana
what do you mean by atomic?
Charles Bretana
A: 

As a general rule, I think the object should create the collection and provide methods for manipulating it; add/get/remove. When following this rule, you should not provide methods for setting the collection directly. If you want a method like setSomeCollection(Collection someCollection) for convenience, the implementation of this method should not set the reference within the object, but copy the values from the method parameter collection to the collection within the object;

public void setSomeCollection(Collection someCollection) {
   this.someCollection.clear();
   this.someCollection.addAll(someCollection);
}

You should do this, so clients of your API cannot get access to the collection that your class maintains. If they do, they can manipulate it without using objects of your class and violate constraints that your class guarantees.

The same is true if providing a getter; you should either return a copy of your internal colleciton, or a read-only version of it. Apache commons-collections and google-collections provide methods for creating immutable wrappers around a collection, aswell as the ones that come with Java in the java.util package; java.util.Collections.unmodifiable*.

Bent André Solheim