//****************************** // Written by Peter Golde // Copyright (c) 2004-2005, Wintellect // // Use and restribution of this code is subject to the license agreement // contained in the file "License.txt" accompanying this file. //****************************** using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; namespace Wintellect.PowerCollections { /// /// CollectionBase is a base class that can be used to more easily implement the /// generic ICollection<T> and non-generic ICollection interfaces. /// /// /// To use CollectionBase as a base class, the derived class must override /// the Count, GetEnumerator, Add, Clear, and Remove methods. /// ICollection<T>.Contains need not be implemented by the /// derived class, but it should be strongly considered, because the CollectionBase implementation /// may not be very efficient. /// /// The item type of the collection. [Serializable] [DebuggerDisplay("{DebuggerDisplayString()}")] public abstract class CollectionBase : ICollection, ICollection { /// /// Creates a new CollectionBase. /// protected CollectionBase() { } /// /// Shows the string representation of the collection. The string representation contains /// a list of the items in the collection. Contained collections (except string) are expanded /// recursively. /// /// The string representation of the collection. public override string ToString() { return Algorithms.ToString(this); } #region ICollection Members /// /// Must be overridden to allow adding items to this collection. /// ///

This method is not abstract, although derived classes should always /// override it. It is not abstract because some derived classes may wish to reimplement /// Add with a different return type (typically bool). In C#, this can be accomplished /// with code like the following:

/// /// public class MyCollection<T>: CollectionBase<T>, ICollection<T> /// { /// public new bool Add(T item) { /// /* Add the item */ /// } /// /// void ICollection<T>.Add(T item) { /// Add(item); /// } /// } /// ///
/// Item to be added to the collection. /// Always throws this exception to indicated /// that the method must be overridden or re-implemented in the derived class. public virtual void Add(T item) { throw new NotImplementedException(Strings.MustOverrideOrReimplement); } /// /// Must be overridden to allow clearing this collection. /// public abstract void Clear(); /// /// Must be overridden to allow removing items from this collection. /// /// True if existed in the collection and /// was removed. False if did not exist in the collection. public abstract bool Remove(T item); /// /// Determines if the collection contains a particular item. This default implementation /// iterates all of the items in the collection via GetEnumerator, testing each item /// against using IComparable<T>.Equals or /// Object.Equals. /// /// You should strongly consider overriding this method to provide /// a more efficient implementation, or if the default equality comparison /// is inappropriate. /// The item to check for in the collection. /// True if the collection contains , false otherwise. public virtual bool Contains(T item) { IEqualityComparer equalityComparer = EqualityComparer.Default; foreach (T i in this) { if (equalityComparer.Equals(i, item)) return true; } return false; } /// /// Copies all the items in the collection into an array. Implemented by /// using the enumerator returned from GetEnumerator to get all the items /// and copy them to the provided array. /// /// Array to copy to. /// Starting index in to copy to. public virtual void CopyTo(T[] array, int arrayIndex) { int count = this.Count; if (count == 0) return; if (array == null) throw new ArgumentNullException("array"); if (count < 0) throw new ArgumentOutOfRangeException("count", count, Strings.ArgMustNotBeNegative); if (arrayIndex < 0) throw new ArgumentOutOfRangeException("arrayIndex", arrayIndex, Strings.ArgMustNotBeNegative); if (arrayIndex >= array.Length || count > array.Length - arrayIndex) throw new ArgumentException("arrayIndex", Strings.ArrayTooSmall); int index = arrayIndex, i = 0; foreach (T item in (ICollection)this) { if (i >= count) break; array[index] = item; ++index; ++i; } } /// /// Creates an array of the correct size, and copies all the items in the /// collection into the array, by calling CopyTo. /// /// An array containing all the elements in the collection, in order. public virtual T[] ToArray() { int count = this.Count; T[] array = new T[count]; CopyTo(array, 0); return array; } /// /// Must be overridden to provide the number of items in the collection. /// /// The number of items in the collection. public abstract int Count { get; } /// /// Indicates whether the collection is read-only. Always returns false. /// /// Always returns false. bool ICollection.IsReadOnly { get { return false; } } /// /// Provides a read-only view of this collection. The returned ICollection<T> provides /// a view of the collection that prevents modifications to the collection. Use the method to provide /// access to the collection without allowing changes. Since the returned object is just a view, /// changes to the collection will be reflected in the view. /// /// An ICollection<T> that provides read-only access to the collection. public virtual ICollection AsReadOnly() { return Algorithms.ReadOnly(this); } #endregion #region Delegate operations /// /// Determines if the collection contains any item that satisfies the condition /// defined by . /// /// A delegate that defines the condition to check for. /// True if the collection contains one or more items that satisfy the condition /// defined by . False if the collection does not contain /// an item that satisfies . public virtual bool Exists(Predicate predicate) { if (predicate == null) throw new ArgumentNullException("predicate"); return Algorithms.Exists(this, predicate); } /// /// Determines if all of the items in the collection satisfy the condition /// defined by . /// /// A delegate that defines the condition to check for. /// True if all of the items in the collection satisfy the condition /// defined by , or if the collection is empty. False if one or more items /// in the collection do not satisfy . public virtual bool TrueForAll(Predicate predicate) { if (predicate == null) throw new ArgumentNullException("predicate"); return Algorithms.TrueForAll(this, predicate); } /// /// Counts the number of items in the collection that satisfy the condition /// defined by . /// /// A delegate that defines the condition to check for. /// The number of items in the collection that satisfy . public virtual int CountWhere(Predicate predicate) { if (predicate == null) throw new ArgumentNullException("predicate"); return Algorithms.CountWhere(this, predicate); } /// /// Enumerates the items in the collection that satisfy the condition defined /// by . /// /// A delegate that defines the condition to check for. /// An IEnumerable<T> that enumerates the items that satisfy the condition. public virtual IEnumerable FindAll(Predicate predicate) { if (predicate == null) throw new ArgumentNullException("predicate"); return Algorithms.FindWhere(this, predicate); } /// /// Removes all the items in the collection that satisfy the condition /// defined by . /// /// A delegate that defines the condition to check for. /// Returns a collection of the items that were removed, in sorted order. public virtual ICollection RemoveAll(Predicate predicate) { if (predicate == null) throw new ArgumentNullException("predicate"); return Algorithms.RemoveWhere(this, predicate); } /// /// Performs the specified action on each item in this collection. /// /// An Action delegate which is invoked for each item in this collection. public virtual void ForEach(Action action) { if (action == null) throw new ArgumentNullException("action"); Algorithms.ForEach(this, action); } /// /// Convert this collection of items by applying a delegate to each item in the collection. The resulting enumeration /// contains the result of applying to each item in this collection, in /// order. /// /// The type each item is being converted to. /// A delegate to the method to call, passing each item in this collection. /// An IEnumerable<TOutput^gt; that enumerates the resulting collection from applying to each item in this collection in /// order. /// is null. public virtual IEnumerable ConvertAll(Converter converter) { if (converter == null) throw new ArgumentNullException("converter"); return Algorithms.Convert(this, converter); } #endregion #region IEnumerable Members /// /// Must be overridden to enumerate all the members of the collection. /// /// A generic IEnumerator<T> that can be used /// to enumerate all the items in the collection. public abstract IEnumerator GetEnumerator(); #endregion #region ICollection Members /// /// Copies all the items in the collection into an array. Implemented by /// using the enumerator returned from GetEnumerator to get all the items /// and copy them to the provided array. /// /// Array to copy to. /// Starting index in to copy to. void ICollection.CopyTo(Array array, int index) { int count = this.Count; if (count == 0) return; if (array == null) throw new ArgumentNullException("array"); if (index < 0) throw new ArgumentOutOfRangeException("index", index, Strings.ArgMustNotBeNegative); if (index >= array.Length || count > array.Length - index) throw new ArgumentException("index", Strings.ArrayTooSmall); int i = 0; foreach (object o in (ICollection)this) { if (i >= count) break; array.SetValue(o, index); ++index; ++i; } } /// /// Indicates whether the collection is synchronized. /// /// Always returns false, indicating that the collection is not synchronized. bool ICollection.IsSynchronized { get { return false; } } /// /// Indicates the synchronization object for this collection. /// /// Always returns this. object ICollection.SyncRoot { get { return this; } } #endregion #region IEnumerable Members /// /// Provides an IEnumerator that can be used to iterate all the members of the /// collection. This implementation uses the IEnumerator<T> that was overridden /// by the derived classes to enumerate the members of the collection. /// /// An IEnumerator that can be used to iterate the collection. IEnumerator IEnumerable.GetEnumerator() { foreach (T item in this) { yield return item; } } #endregion /// /// Display the contents of the collection in the debugger. This is intentionally private, it is called /// only from the debugger due to the presence of the DebuggerDisplay attribute. It is similar /// format to ToString(), but is limited to 250-300 characters or so, so as not to overload the debugger. /// /// The string representation of the items in the collection, similar in format to ToString(). internal string DebuggerDisplayString() { const int MAXLENGTH = 250; System.Text.StringBuilder builder = new System.Text.StringBuilder(); builder.Append('{'); // Call ToString on each item and put it in. bool firstItem = true; foreach (T item in this) { if (builder.Length >= MAXLENGTH) { builder.Append(",..."); break; } if (!firstItem) builder.Append(','); if (item == null) builder.Append("null"); else builder.Append(item.ToString()); firstItem = false; } builder.Append('}'); return builder.ToString(); } } }