The most obvious additions to the collection types starting within the .NET 2.0 Framework are the types defined within the System.Collections.Generic namespace. These types are strongly typed, thus giving the compiler a bigger type-safety hammer to wield when ferreting out type-mismatch bugs at compile time. In addition, when used to contain value types, they are much more efficient, because there is no gratuitous boxing. Arguably, the root type of all the generic collection types is ICollection<T>. I have included the declaration for it here:

public interface ICollection<T> : IEnumerable<T>, IEnumerable
{
int Count { get; }
bool IsReadOnly { get; }
void Add( T item );
void Clear();
bool Contains( T item );
void CopyTo( T[] array, int arrayIndex );
bool Remove( T item );
}

For the sake of comparison, I’ve included the nongeneric ICollection interface definition as well:

public interface ICollection : IEnumerable
{
int Count { get; }
bool IsSynchronized { get; }
object SyncRoot { get; }
void CopyTo( Array array, int index );
}

Now, let’s take a look at the differences and what that means for your code. One thing that has been missing with the nongeneric collections is a uniform interface for managing the contents of the collection. For example, the nongeneric Stack and Queue types both have a Clear method to erase their contents. As expected, they both implement ICollection. However, because ICollection doesn’t contain any modifying methods, you generally can’t treat instances of these two types polymorphically within code. Thus, you would always have to cast an instance variable to type Stack in order to call Stack.Clear, and cast to type Queue in order to call Queue.Clear.

ICollection<T> helps this problem by declaring some methods for modifying the collection. As with most general-use solutions, it does not necessarily apply to all situations. For example, ICollection<T> also declares an IsReadOnly property, because sometimes you need to introduce an immutable collection in your design. For those instances, you would expect calls to Add, Clear, and Remove to throw an InvalidOperationException.

Since a main purpose of ICollection<T> is to provide stronger type safety, it only makes sense that ICollection<T> provides its own version of CopyTo that is strongly typed. Whereas ICollection.CopyTo knows that the first parameter is an array and accepts a System.Array reference as its first parameter, ICollection<T>.CopyTo is given the concrete array type in its first parameter. Clearly, you can only pass a single dimension array to ICollection<T>.CopyTo. The fact is that the nongeneric ICollection.CopyTo only accepts an array of single dimension as well, but because the compiler cannot determine the rank of a System.Array type at compile time, you get a runtime exception of the type ArgumentException if you
pass an array with more than one dimension to a proper implementation of ICollection.CopyTo. Notice that I said "a proper implementation." Not only is the caller of ICollection.CopyTo supposed to know this rule, but so is the type implementing ICollection. The added type information in
ICollection<T>.CopyTo not only protects both the caller and the implementer from making this mistake, it also provides greater efficiency.

You’ll notice that all of the generic collection types implement both ICollection<T> and ICollection. Both interfaces provide useful utility to the container type. Any methods in ICollection that overlap with ICollection<T> should be implemented explicitly.

For better performance, it’s recommended that calling code determines if such operations are forbidden by first checking the IsReadOnly property, thus avoiding the exception altogether. Of course, if the end result of IsReadOnly returning true is that you throw an exception, then there is no gain.

When defining your own collection types, you should derive from Collection<T> in the System.Collections.ObjectModel namespace unless there is a good reason not to do so. For instance, Collection<T> might have some functionality that you don’t want, or you must be explicit about how the items are stored in the collection and has protected virtual methods that you can override to control its behavior. When you don’t derive from Collection<T>, your job is much more laborious, because you must reimplement most of what Collection<T> already implements. If you are creating your own custom dictionary type, derive from the Parallel Computing Platform team at Microsoft and their locking techniques are finely tuned for efficiency in concurrent multithreaded environments.

Source Of Information : Apress Accelerated C Sharp 2010

0 comments


Subscribe to Developer Techno ?
Enter your email address:

Delivered by FeedBurner