We'd like a way to gather up objects as they are created so that we can manage them as a group and operate on them collectively, along with referring to them individually when necessary. For example:
The Student Registration System (SRS) application as a whole may need to step through all of the Course objects in the current schedule of classes to determine which of them don't yet have any students registered for them, possibly to cancel these courses.
We use a special type of object called a collection to group other objects. A collection object can hold/contain multiple references to some other type of object. Think of a collection like an egg carton, and the objects it holds like the eggs! Both are objects, but with decidedly different properties.
Because collections are implemented as objects, this implies that
Collections must be instantiated before they can first be used.
Collections are defined by classes that in turn define methods for "getting" and "setting" their contents.
By virtue of being objects, OO collections are encapsulated, and hence take full advantage of information hiding.
Let's discuss each of these three matters in turn.
We can't merely declare a collection:
All this does is to declare a reference variable of type CollectionType. Until we "hand" c a CollectionType object to refer to, c is said to have the value null.
ArrayList is one of C#'s predefined collection types, defined by the.NET Framework Class Library (FCL).We'll introduce the ArrayList class in this chapter, and we'll then go into greater detail about ArrayLists, along with several other collection types, in Chapter 13.
c = new CollectionType();
c = new ArrayList();
Think of the newly created CollectionType object as an empty "egg carton," and the reference variable c as the handle that allows us to locate and access (reference) this egg carton whenever we'd like.
Then, as we instantiate objects ("eggs"), we'll place their references into the various egg carton compartments:
Student s = new Student(); // Pseudocode. c. Add(s);
So, rather than thinking of the objects as eggs that are physically placed inside of the egg carton compartments, we should really think of the objects as balloons whose strings are tied inside the egg carton compartments, as illustrated in Figure 6-1. That is, the objects themselves live physically outside of the collection, but can be located through their references, which are stored within the collection.
Thus, perhaps a more appropriate analogy than a collection as an egg carton would be that of a collection as an address book: we make an entry in the address book (collection) for each of the persons (objects) that we wish to contact, but the actual persons themselves are physically remote (see Figure 6-2).
Note that C# collections can also hold references to value-type variables (int, float, etc.) because in the C# language, value-type variables are actually implemented as objects. This is in contrast to Java, where simple data types— int, float, etc.—are not objects, and hence cannot be stored "as is" in Java collections.
Here is a code snippet that illustrates the use of a collection in C#; we use a bit of pseudocode here to emphasize the common features of collections.
// Instantiate a collection object (pseudocode). CollectionType x = new CollectionType(); // Create a few Student objects. Student a = new Student(); Student b = new Student(); Student c = new Student(); // Store all three students in the collection by calling the appropriate // method for adding objects to the collection ... x.Add(a); x.Add(b); x.Add(c); // ... and then retrieve the first one. x.Retrieve(0); // we typically start counting at 0.
We don't need to know the private details of how object references are stored internally to a specific type of collection in order to use the collection properly; we only need to know a collection's public features—in particular, its method headers and properties—in order to choose an appropriate collection type for a particular situation and to use it effectively.
This is a tiny bit misleading: in the case of huge collections, it is helpful to know a little bit about the inner workings of various collection types so as to choose the one that is most efficient; we'll consider this matter further in Chapter 13.
Virtually all collections, regardless of type and regardless of the programming language in which they are implemented, provide, at a minimum, methods for
Adding object (reference)s
Removing object (reference)s
Retrieving specific individual object (reference)s
Iterating through the object (reference)s in some predetermined order
Getting a count of the number of object (reference)s in the container
Answering a true/false question as to whether a particular object is referenced by the container or not
Throughout this chapter, we'll talk casually about manipulating objects in collections, but please remember that, with C#, what we really mean is that we're manipulating object references.