//****************************** // 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 { /// /// ReadOnlyCollectionBase is a base class that can be used to more easily implement the /// generic ICollection<T> and non-generic ICollection interfaces for a read-only collection: /// a collection that does not allow adding or removing elements. /// /// /// To use ReadOnlyCollectionBase as a base class, the derived class must override /// the Count and GetEnumerator methods. /// ICollection<T>.Contains need not be implemented by the /// derived class, but it should be strongly considered, because the ReadOnlyCollectionBase implementation /// may not be very efficient. /// /// The item type of the collection. [Serializable] [DebuggerDisplay("{DebuggerDisplayString()}")] public abstract class ReadOnlyCollectionBase : ICollection, ICollection { /// /// Creates a new ReadOnlyCollectionBase. /// protected ReadOnlyCollectionBase() { } /// /// Throws an NotSupportedException stating that this collection cannot be modified. /// private void MethodModifiesCollection() { throw new NotSupportedException(string.Format(Strings.CannotModifyCollection, Util.SimpleClassName(this.GetType()))); } #region Delegate operations /// /// Shows the string representation of the collection. The string representation contains /// a list of the items in the collection. /// /// The string representation of the collection. public override string ToString() { return Algorithms.ToString(this); } /// /// 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 IEnumerable FindAll(Predicate predicate) { if (predicate == null) throw new ArgumentNullException("predicate"); return Algorithms.FindWhere(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 Delegate operations #region ICollection Members /// /// This method throws an NotSupportedException /// stating the collection is read-only. /// /// Item to be added to the collection. /// Always thrown. void ICollection.Add(T item) { MethodModifiesCollection(); } /// /// This method throws an NotSupportedException /// stating the collection is read-only. /// /// Always thrown. void ICollection.Clear() { MethodModifiesCollection(); } /// /// This method throws an NotSupportedException /// stating the collection is read-only. /// /// Item to be removed from the collection. /// Always thrown. bool ICollection.Remove(T item) { MethodModifiesCollection(); return false; } /// /// 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. /// 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. Returns the value /// of readOnly that was provided to the constructor. /// /// Always true. bool ICollection.IsReadOnly { get { return true; } } #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 (count < 0) throw new ArgumentOutOfRangeException("count", count, Strings.ArgMustNotBeNegative); 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(); } } }