//******************************
// 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();
}
}
}