The types defined in the System.Collections namespace are fine as general-purpose collection types, but frequently programmers require specialized semantics around a collection class; for example, a collection of booleans could be more efficiently stored as a single System.Int64, whereas simply placing System.Boolean instances into a general-purpose collection is far more wasteful, in both memory and processing time.
Additionally, programmers often grow frustrated with the lack of type-safety in the general-purpose containers; not only does a programmer have to typecast any object obtained out of the container, but the container itself holds no intrinsic logic to "screen out" unwanted types being inserted into the container. (This is in marked contrast to C++ template-based collections such as the STL, in which the attempt to put a string into a container of integers causes a compile-time error.)
Container specialization isn't limited to storage type; at times, a programmer desires different processing behavior than the general-purpose container provides. As an example, consider the System.Collections.IDictionary interface. Note that it clearly defines a mapping of keys to values; however, it is only implicitly understood that the exact same key must be produced to obtain the value desired. In most cases, this is exactly what's needed; however, there are times when a less stringent retrieval mechanism is preferred. For example, perhaps a case-insensitive match is wanted instead of doing an exact match for a string key. The System.Collections.Specialized namespace includes collections designed to address these cases. Figure 28-1 shows the types in this namespace.