//****************************** // 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; namespace Wintellect.PowerCollections { /// /// ReadOnlyListBase is an abstract class that can be used as a base class for a read-only collection that needs /// to implement the generic IList<T> and non-generic IList collections. The derived class needs /// to override the Count property and the get part of the indexer. The implementation /// of all the other methods in IList<T> and IList are handled by ListBase. /// /// [Serializable] public abstract class ReadOnlyListBase : ReadOnlyCollectionBase, IList, IList { /// /// Creates a new ReadOnlyListBase. /// protected ReadOnlyListBase() { } /// /// Throws an NotSupportedException stating that this collection cannot be modified. /// private void MethodModifiesCollection() { throw new NotSupportedException(string.Format(Strings.CannotModifyCollection, Util.SimpleClassName(this.GetType()))); } /// /// The property must be overridden by the derived class to return the number of /// items in the list. /// /// The number of items in the list. public abstract override int Count { get;} /// /// The get part of the indexer must be overridden by the derived class to get /// values of the list at a particular index. /// /// The index in the list to get or set an item at. The /// first item in the list has index 0, and the last has index Count-1. /// The item at the given index. /// is /// less than zero or greater than or equal to Count. public virtual T this[int index] { get { throw new NotImplementedException(Strings.MustOverrideIndexerGet); } set { MethodModifiesCollection(); } } /// /// Enumerates all of the items in the list, in order. The item at index 0 /// is enumerated first, then the item at index 1, and so on. /// /// An IEnumerator<T> that enumerates all the /// items in the list. public override IEnumerator GetEnumerator() { int count = Count; for (int i = 0; i < count; ++i) { yield return this[i]; } } /// /// Determines if the list contains any item that compares equal to . /// The implementation simply checks whether IndexOf(item) returns a non-negative value. /// /// Equality in the list is determined by the default sense of /// equality for T. If T implements IComparable<T>, the /// Equals method of that interface is used to determine equality. Otherwise, /// Object.Equals is used to determine equality. /// The item to search for. /// True if the list contains an item that compares equal to . public override bool Contains(T item) { return (IndexOf(item) >= 0); } /// /// Copies all the items in the list, in order, to , /// starting at index 0. /// /// The array to copy to. This array must have a size /// that is greater than or equal to Count. public virtual void CopyTo(T[] array) { this.CopyTo(array, 0); } /// /// Copies all the items in the list, in order, to , /// starting at . /// /// The array to copy to. This array must have a size /// that is greater than or equal to Count + arrayIndex. /// The starting index in /// to copy to. public override void CopyTo(T[] array, int arrayIndex) { base.CopyTo(array, arrayIndex); } /// /// Copies a range of elements from the list to , /// starting at . /// /// The starting index in the source list of the range to copy. /// The array to copy to. This array must have a size /// that is greater than or equal to Count + arrayIndex. /// The starting index in /// to copy to. /// The number of items to copy. public virtual void CopyTo(int index, T[] array, int arrayIndex, int count) { Range(index, count).CopyTo(array, arrayIndex); } /// /// Finds the first item in the list that satisfies the condition /// defined by . If no item matches the condition, than /// the default value for T (null or all-zero) is returned. /// /// If the default value for T (null or all-zero) matches the condition defined by , /// and the list might contain the default value, then it is impossible to distinguish the different between finding /// the default value and not finding any item. To distinguish these cases, use . /// A delegate that defined the condition to check for. /// The first item that satisfies the condition . If no item satisfies that /// condition, the default value for T is returned. /// public virtual T Find(Predicate predicate) { return Algorithms.FindFirstWhere(this, predicate); } /// /// Finds the first item in the list that satisfies the condition /// defined by . /// /// A delegate that defines the condition to check for. /// If true is returned, this parameter receives the first item in the list /// that satifies the condition defined by . /// True if an item that satisfies the condition was found. False /// if no item in the list satisfies that condition. public virtual bool TryFind(Predicate predicate, out T foundItem) { return Algorithms.TryFindFirstWhere(this, predicate, out foundItem); } /// /// Finds the last item in the list that satisfies the condition /// defined by . If no item matches the condition, than /// the default value for T (null or all-zero) is returned. /// /// If the default value for T (null or all-zero) matches the condition defined by , /// and the list might contain the default value, then it is impossible to distinguish the different between finding /// the default value and not finding any item. To distinguish these cases, use . /// A delegate that defined the condition to check for. /// The last item that satisfies the condition . If no item satisfies that /// condition, the default value for T is returned. /// public virtual T FindLast(Predicate predicate) { return Algorithms.FindLastWhere(this, predicate); } /// /// Finds the last item in the list that satisfies the condition /// defined by . /// /// A delegate that defines the condition to check for. /// If true is returned, this parameter receives the last item in the list /// that satifies the condition defined by . /// True if an item that satisfies the condition was found. False /// if no item in the list satisfies that condition. public virtual bool TryFindLast(Predicate predicate, out T foundItem) { return Algorithms.TryFindLastWhere(this, predicate, out foundItem); } /// /// Finds the index of the first item in the list that satisfies the condition /// defined by . If no item matches the condition, -1 is returned. /// /// A delegate that defined the condition to check for. /// The index of the first item that satisfies the condition . If no item satisfies that /// condition, -1 is returned. public virtual int FindIndex(Predicate predicate) { return Algorithms.FindFirstIndexWhere(this, predicate); } /// /// Finds the index of the first item, in the range of items extending from to the end, that satisfies the condition /// defined by . If no item matches the condition, -1 is returned. /// /// A delegate that defined the condition to check for. /// The starting index of the range to check. /// The index of the first item in the given range that satisfies the condition . If no item satisfies that /// condition, -1 is returned. public virtual int FindIndex(int index, Predicate predicate) { int foundIndex = Algorithms.FindFirstIndexWhere(Range(index, Count - index), predicate); if (foundIndex < 0) return -1; else return foundIndex + index; } /// /// Finds the index of the first item, in the range of items starting from , that satisfies the condition /// defined by . If no item matches the condition, -1 is returned. /// /// A delegate that defined the condition to check for. /// The starting index of the range to check. /// The number of items in range to check. /// The index of the first item in the given range that satisfies the condition . If no item satisfies that /// condition, -1 is returned. public virtual int FindIndex(int index, int count, Predicate predicate) { int foundIndex = Algorithms.FindFirstIndexWhere(Range(index, count), predicate); if (foundIndex < 0) return -1; else return foundIndex + index; } /// /// Finds the index of the last item in the list that satisfies the condition /// defined by . If no item matches the condition, -1 is returned. /// /// A delegate that defined the condition to check for. /// The index of the last item that satisfies the condition . If no item satisfies that /// condition, -1 is returned. public virtual int FindLastIndex(Predicate predicate) { return Algorithms.FindLastIndexWhere(this, predicate); } /// /// Finds the index of the last item, in the range of items extending from the beginning /// of the list to , that satisfies the condition /// defined by . If no item matches the condition, -1 is returned. /// /// A delegate that defined the condition to check for. /// The ending index of the range to check. /// The index of the last item in the given range that satisfies the condition . If no item satisfies that /// condition, -1 is returned. public virtual int FindLastIndex(int index, Predicate predicate) { return Algorithms.FindLastIndexWhere(Range(0, index + 1), predicate); } /// /// Finds the index of the last item, in the range of items ending at , that satisfies the condition /// defined by . If no item matches the condition, -1 is returned. /// /// A delegate that defined the condition to check for. /// The ending index of the range to check. /// The number of items in range to check. /// The index of the last item in the given range that satisfies the condition . If no item satisfies that /// condition, -1 is returned. public virtual int FindLastIndex(int index, int count, Predicate predicate) { int foundIndex = Algorithms.FindLastIndexWhere(Range(index - count + 1, count), predicate); if (foundIndex >= 0) return foundIndex + index - count + 1; else return -1; } /// /// Finds the index of the first item in the list that is equal to . /// /// The default implementation of equality for type T is used in the search. This is the /// equality defined by IComparable<T> or object.Equals. /// The item to search fror. /// The index of the first item in the list that that is equal to . If no item is equal /// to , -1 is returned. public virtual int IndexOf(T item) { return Algorithms.FirstIndexOf(this, item, EqualityComparer.Default); } /// /// Finds the index of the first item, in the range of items extending from to the end, /// that is equal to . /// /// The default implementation of equality for type T is used in the search. This is the /// equality defined by IComparable<T> or object.Equals. /// The item to search fror. /// The starting index of the range to check. /// The index of the first item in the given range that that is equal to . If no item is equal /// to , -1 is returned. public virtual int IndexOf(T item, int index) { int foundIndex = Algorithms.FirstIndexOf(Range(index, Count - index), item, EqualityComparer.Default); if (foundIndex >= 0) return foundIndex + index; else return -1; } /// /// Finds the index of the first item, in the range of items starting from , /// that is equal to . /// /// The default implementation of equality for type T is used in the search. This is the /// equality defined by IComparable<T> or object.Equals. /// The item to search fror. /// The starting index of the range to check. /// The number of items in range to check. /// The index of the first item in the given range that that is equal to . If no item is equal /// to , -1 is returned. public virtual int IndexOf(T item, int index, int count) { int foundIndex = Algorithms.FirstIndexOf(Range(index, count), item, EqualityComparer.Default); if (foundIndex >= 0) return foundIndex + index; else return -1; } /// /// Finds the index of the last item in the list that is equal to . /// /// The default implementation of equality for type T is used in the search. This is the /// equality defined by IComparable<T> or object.Equals. /// The item to search fror. /// The index of the last item in the list that that is equal to . If no item is equal /// to , -1 is returned. public virtual int LastIndexOf(T item) { return Algorithms.LastIndexOf(this, item, EqualityComparer.Default); } /// /// Finds the index of the last item, in the range of items extending from the beginning /// of the list to , that is equal to . /// /// The default implementation of equality for type T is used in the search. This is the /// equality defined by IComparable<T> or object.Equals. /// The item to search fror. /// The ending index of the range to check. /// The index of the last item in the given range that that is equal to . If no item is equal /// to , -1 is returned. public virtual int LastIndexOf(T item, int index) { int foundIndex = Algorithms.LastIndexOf(Range(0, index + 1), item, EqualityComparer.Default); return foundIndex; } /// /// Finds the index of the last item, in the range of items ending at , /// that is equal to . /// /// The default implementation of equality for type T is used in the search. This is the /// equality defined by IComparable<T> or object.Equals. /// The item to search for. /// The ending index of the range to check. /// The number of items in range to check. /// The index of the last item in the given range that that is equal to . If no item is equal /// to , -1 is returned. public virtual int LastIndexOf(T item, int index, int count) { int foundIndex = Algorithms.LastIndexOf(Range(index - count + 1, count), item, EqualityComparer.Default); if (foundIndex >= 0) return foundIndex + index - count + 1; else return -1; } /// /// Returns a view onto a sub-range of this list. Items are not copied; the /// returned IList<T> is simply a different view onto the same underlying items. /// /// /// This method can be used to apply an algorithm to a portion of a list. For example: /// Algorithms.Reverse(deque.Range(3, 6)) /// will return the reverse opf the 6 items beginning at index 3. /// The starting index of the view. /// The number of items in the view. /// A list that is a view onto the given sub-part of this list. /// or is negative. /// + is greater than the /// size of the list. public virtual IList Range(int start, int count) { return Algorithms.Range(this, start, count); } /// /// Inserts a new item at the given index. This implementation throws a NotSupportedException /// indicating that the list is read-only. /// /// The index in the list to insert the item at. After the /// insertion, the inserted item is located at this index. The /// first item in the list has index 0. /// The item to insert at the given index. /// Always thrown. void IList.Insert(int index, T item) { MethodModifiesCollection(); } /// /// Removes the item at the given index. This implementation throws a NotSupportedException /// indicating that the list is read-only. /// /// The index in the list to remove the item at. The /// first item in the list has index 0. /// Always thrown. void IList.RemoveAt(int index) { MethodModifiesCollection(); } /// /// Adds an item to the end of the list. This implementation throws a NotSupportedException /// indicating that the list is read-only. /// /// The item to add to the list. /// Always thrown. int IList.Add(object value) { MethodModifiesCollection(); return -1; } /// /// Removes all the items from the list, resulting in an empty list. This implementation throws a NotSupportedException /// indicating that the list is read-only. /// /// Always thrown. void IList.Clear() { MethodModifiesCollection(); } /// /// Determines if the list contains any item that compares equal to . /// /// Equality in the list is determined by the default sense of /// equality for T. If T implements IComparable<T>, the /// Equals method of that interface is used to determine equality. Otherwise, /// Object.Equals is used to determine equality. /// The item to search for. bool IList.Contains(object value) { if (value is T || value == null) return Contains((T)value); else return false; } /// /// Find the first occurrence of an item equal to /// in the list, and returns the index of that item. /// /// Equality in the list is determined by the default sense of /// equality for T. If T implements IComparable<T>, the /// Equals method of that interface is used to determine equality. Otherwise, /// Object.Equals is used to determine equality. /// The item to search for. /// The index of , or -1 if no item in the /// list compares equal to . int IList.IndexOf(object value) { if (value is T || value == null) return IndexOf((T)value); else return -1; } /// /// Insert a new item at the given index. This implementation throws a NotSupportedException /// indicating that the list is read-only. /// /// The index in the list to insert the item at. After the /// insertion, the inserted item is located at this index. The /// first item in the list has index 0. /// The item to insert at the given index. /// Always thrown. void IList.Insert(int index, object value) { MethodModifiesCollection(); } /// /// Returns whether the list is a fixed size. This implementation always returns true. /// /// Alway true, indicating that the list is fixed size. bool IList.IsFixedSize { get { return true; } } /// /// Returns whether the list is read only. This implementation always returns true. /// /// Alway true, indicating that the list is read-only. bool IList.IsReadOnly { get { return true; } } /// /// Searches the list for the first item that compares equal to . /// If one is found, it is removed. Otherwise, the list is unchanged. This implementation throws a NotSupportedException /// indicating that the list is read-only. /// /// Equality in the list is determined by the default sense of /// equality for T. If T implements IComparable<T>, the /// Equals method of that interface is used to determine equality. Otherwise, /// Object.Equals is used to determine equality. /// The item to remove from the list. /// Always thrown. void IList.Remove(object value) { MethodModifiesCollection(); } /// /// Removes the item at the given index. This implementation throws a NotSupportedException /// indicating that the list is read-only. /// /// The index in the list to remove the item at. The /// first item in the list has index 0. /// Always thrown. void IList.RemoveAt(int index) { MethodModifiesCollection(); } /// /// Gets or sets the value at a particular index in the list. /// /// The index in the list to get or set an item at. The /// first item in the list has index 0, and the last has index Count-1. /// The item at the given index. /// is /// less than zero or greater than or equal to Count. /// cannot be converted to T. /// Always thrown from the setter, indicating that the list /// is read-only. object IList.this[int index] { get { return this[index]; } set { MethodModifiesCollection(); } } } }