/Utilities/Collections/CollectionBase.cs
C# | 1303 lines | 908 code | 114 blank | 281 comment | 70 complexity | a89a7dedbf477df6bbad60bc812c8075 MD5 | raw file
Possible License(s): Apache-2.0
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Text;
- using Delta.Utilities.Helpers;
- using NUnit.Framework;
-
- namespace Delta.Utilities.Collections
- {
- /// <summary>
- /// CollectionBase is a base class that can be used to more easily implement
- /// the generic ICollection<T> and non-generic ICollection interfaces.
- /// </summary>
- /// <typeparam name="T">Data type</typeparam>
- [DebuggerDisplay("{DebuggerToString()}")]
- public abstract class CollectionBase<T> : ICollection<T>, ICollection
- {
- #region Count (Public)
- /// <summary>
- /// Must be overridden to provide the number of items in the collection.
- /// </summary>
- /// <value>The number of items in the collection.</value>
- /// <typeparam name="T">T</typeparam>
- public abstract int Count
- {
- get;
- }
- #endregion
-
- #region Private
-
- #region IsReadOnly (Private)
- /// <summary>
- /// Indicates whether the collection is read-only. Always returns false.
- /// </summary>
- /// <value>Always returns false.</value>
- /// <typeparam name="T">T</typeparam>
- bool ICollection<T>.IsReadOnly
- {
- get
- {
- return false;
- } // get
- }
- #endregion
-
- #region IsSynchronized (Private)
- /// <summary>
- /// Indicates whether the collection is synchronized.
- /// </summary>
- /// <value>Always returns false, indicating that the collection is not
- /// synchronized.</value>
- /// <typeparam name="T">T</typeparam>
- bool ICollection.IsSynchronized
- {
- get
- {
- return false;
- } // get
- }
- #endregion
-
- #region SyncRoot (Private)
- /// <summary>
- /// Indicates the synchronization object for this collection.
- /// </summary>
- /// <value>Always returns this.</value>
- /// <typeparam name="T">T</typeparam>
- object ICollection.SyncRoot
- {
- get
- {
- return this;
- } // get
- }
- #endregion
-
- #endregion
-
- #region ICollection Members
- /// <summary>
- /// 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.
- /// </summary>
- /// <param name="array">Array to copy to.</param>
- /// <param name="index">Starting index in <paramref name="array"/> to
- /// copy to.</param>
- void ICollection.CopyTo(Array array, int index)
- {
- int count = Count;
-
- if (count == 0)
- {
- return;
- }
-
- if (array == null)
- {
- throw new ArgumentNullException("array");
- }
- if (index < 0)
- {
- throw new ArgumentOutOfRangeException(
- "index", "The argument may not be less than zero: " + index);
- }
- if (index >= array.Length ||
- count > array.Length - index)
- {
- throw new ArgumentException(
- "index", "The array is too small to hold all of the items.");
- }
-
- int i = 0;
- foreach (object o in (ICollection)this)
- {
- if (i >= count)
- {
- break;
- }
-
- array.SetValue(o, index);
- ++index;
- ++i;
- }
- }
- #endregion
-
- #region ICollection<T> Members
- /// <summary>
- /// Must be overridden to allow adding items to this collection.
- /// </summary>
- /// <remarks>
- /// 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:
- /// <code>
- /// 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);
- /// }
- /// }
- /// </code>
- /// </remarks>
- /// <param name="item">Item to be added to the collection.</param>
- /// <exception cref="NotImplementedException">Always throws this exception
- /// to indicated that the method must be overridden or re-implemented in
- /// the derived class.</exception>
- public virtual void Add(T item)
- {
- throw new NotSupportedException(
- "This method must be overridden in the derived class.");
- }
-
- /// <summary>
- /// Must be overridden to allow clearing this collection.
- /// </summary>
- public abstract void Clear();
-
- /// <summary>
- /// 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 <paramref name="item"/> using
- /// IComparable<T>.Equals or Object.Equals.
- /// </summary>
- /// <remarks>You should strongly consider overriding this method to provide
- /// a more efficient implementation, or if the default equality comparison
- /// is inappropriate.</remarks>
- /// <param name="item">The item to check for in the collection.</param>
- /// <returns>True if the collection contains <paramref name="item"/>,
- /// false otherwise.</returns>
- public virtual bool Contains(T item)
- {
- IEqualityComparer<T> equalityComparer = EqualityComparer<T>.Default;
- foreach (T i in this)
- {
- if (equalityComparer.Equals(i, item))
- {
- return true;
- }
- }
- return false;
- }
-
- /// <summary>
- /// 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.
- /// </summary>
- /// <param name="array">Array to copy to.</param>
- /// <param name="arrayIndex">Starting index in <paramref name="array"/>
- /// to copy to.</param>
- public virtual void CopyTo(T[] array, int arrayIndex)
- {
- int count = Count;
-
- if (count == 0)
- {
- return;
- }
-
- if (array == null)
- {
- throw new ArgumentNullException("array");
- }
- if (count < 0)
- {
- throw new IndexOutOfRangeException(
- "The count may not be less than zero: " + count);
- }
- if (arrayIndex < 0)
- {
- throw new ArgumentOutOfRangeException(
- "arrayIndex", "The argument may not be less than zero: " +
- arrayIndex);
- }
- if (arrayIndex >= array.Length ||
- count > array.Length - arrayIndex)
- {
- throw new ArgumentException(
- "The array is too small to hold all of the items.", "arrayIndex");
- }
-
- int index = arrayIndex, i = 0;
- foreach (T item in (ICollection<T>)this)
- {
- if (i >= count)
- {
- break;
- }
-
- array[index] = item;
- ++index;
- ++i;
- }
- }
-
- /// <summary>
- /// Must be overridden to allow removing items from this collection.
- /// </summary>
- /// <returns>
- /// True if <paramref name="item"/> existed in the collection and was
- /// removed. False if <paramref name="item"/> did not exist in the
- /// collection.
- /// </returns>
- public abstract bool Remove(T item);
- #endregion
-
- #region IEnumerable Members
- /// <summary>
- /// 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.
- /// </summary>
- /// <returns>An IEnumerator that can be used to iterate the collection.
- /// </returns>
- IEnumerator IEnumerable.GetEnumerator()
- {
- foreach (T item in this)
- {
- yield return item;
- }
- }
- #endregion
-
- #region IEnumerable<T> Members
- /// <summary>
- /// Must be overridden to enumerate all the members of the collection.
- /// </summary>
- /// <returns>A generic IEnumerator<T> that can be used
- /// to enumerate all the items in the collection.</returns>
- public abstract IEnumerator<T> GetEnumerator();
- #endregion
-
- #region ToArray (Public)
- /// <summary>
- /// Creates an array of the correct size, and copies all the items in the
- /// collection into the array, by calling CopyTo.
- /// </summary>
- /// <returns>An array containing all the elements in the collection,
- /// in order.</returns>
- public virtual T[] ToArray()
- {
- int count = Count;
-
- T[] array = new T[count];
- CopyTo(array, 0);
- return array;
- }
- #endregion
-
- #region Exists (Public)
- /// <summary>
- /// Determines if the collection contains any item that satisfies the
- /// condition defined by <paramref name="predicate"/>.
- /// </summary>
- /// <param name="predicate">A delegate that defines the condition to check
- /// for.</param>
- /// <returns>True if the collection contains one or more items that satisfy
- /// the condition defined by <paramref name="predicate"/>. False if the
- /// collection does not contain an item that satisfies
- /// <paramref name="predicate"/>.</returns>
- public virtual bool Exists(Predicate<T> predicate)
- {
- if (predicate == null)
- {
- throw new ArgumentNullException("predicate");
- }
-
- foreach (T item in this)
- {
- if (predicate(item))
- {
- return true;
- }
- }
-
- return false;
- }
- #endregion
-
- #region TrueForAll (Public)
- /// <summary>
- /// Determines if all of the items in the collection satisfy the condition
- /// defined by <paramref name="predicate"/>.
- /// </summary>
- /// <param name="predicate">A delegate that defines the condition to check
- /// for.</param>
- /// <returns>True if all of the items in the collection satisfy the
- /// condition defined by <paramref name="predicate"/>, or if the collection
- /// is empty. False if one or more items in the collection do not satisfy
- /// <paramref name="predicate"/>.</returns>
- public virtual bool TrueForAll(Predicate<T> predicate)
- {
- if (predicate == null)
- {
- throw new ArgumentNullException("predicate");
- }
-
- foreach (T item in this)
- {
- if (!predicate(item))
- {
- return false;
- }
- }
-
- return true;
- }
- #endregion
-
- #region CountWhere (Public)
- /// <summary>
- /// Counts the number of items in the collection that satisfy the condition
- /// defined by <paramref name="predicate"/>.
- /// </summary>
- /// <param name="predicate">A delegate that defines the condition to check
- /// for.</param>
- /// <returns>The number of items in the collection that satisfy
- /// <paramref name="predicate"/>.</returns>
- public virtual int CountWhere(Predicate<T> predicate)
- {
- if (predicate == null)
- {
- throw new ArgumentNullException("predicate");
- }
-
- int count = 0;
- foreach (T item in this)
- {
- if (predicate(item))
- {
- ++count;
- }
- }
-
- return count;
- }
- #endregion
-
- #region FindAll (Public)
- /// <summary>
- /// Enumerates the items in the collection that satisfy the condition
- /// defined by <paramref name="predicate"/>.
- /// </summary>
- /// <param name="predicate">
- /// A delegate that defines the condition to check for.
- /// </param>
- /// <returns>An IEnumerable<T> that enumerates the items that
- /// satisfy the condition.</returns>
- public virtual IEnumerable<T> FindAll(Predicate<T> predicate)
- {
- if (predicate == null)
- {
- throw new ArgumentNullException("predicate");
- }
-
- foreach (T item in this)
- {
- if (predicate(item))
- {
- yield return item;
- }
- }
- }
- #endregion
-
- #region RemoveAll (Public)
- /// <summary>
- /// Removes all the items in the collection that satisfy the condition
- /// defined by <paramref name="predicate"/>.
- /// </summary>
- /// <param name="predicate">A delegate that defines the condition to check
- /// for.</param>
- /// <returns>Returns a collection of the items that were removed, in sorted
- /// order.</returns>
- public virtual ICollection<T> RemoveAll(Predicate<T> predicate)
- {
- if (predicate == null)
- {
- throw new ArgumentNullException("predicate");
- }
-
- /*unused
- if (collection is T[])
- collection = new ArrayWrapper<T>((T[])collection);
- if (collection.IsReadOnly)
- throw new ArgumentException(Strings.ListIsReadOnly, "collection");
- */
-
- IList<T> list = this as IList<T>;
- if (list != null)
- {
- T item;
- int i = -1, j = 0;
- int listCount = list.Count;
- List<T> removed = new List<T>();
-
- // Remove item where predicate is true, compressing items to lower in
- // the list. This is much more efficient than the naive algorithm that
- // uses IList<T>.Remove().
- while (j < listCount)
- {
- item = list[j];
- if (predicate(item))
- {
- removed.Add(item);
- }
- else
- {
- ++i;
- if (i != j)
- {
- list[i] = item;
- }
- }
- ++j;
- }
-
- ++i;
- if (i < listCount)
- {
- // remove items from the end.
- IList fixedList = list as IList;
- if (fixedList != null &&
- fixedList.IsFixedSize)
- {
- // An array or similar. Null out the last elements.
- while (i < listCount)
- {
- list[i++] = default(T);
- }
- }
- else
- {
- // Normal list.
- while (i < listCount)
- {
- list.RemoveAt(listCount - 1);
- --listCount;
- }
- }
- }
-
- return removed;
- }
- else
- {
- // We have to copy all the items to remove to a List, because
- // collections can't be modifed during an enumeration.
- List<T> removed = new List<T>();
-
- foreach (T item in this)
- {
- if (predicate(item))
- {
- removed.Add(item);
- }
- }
-
- foreach (T item in removed)
- {
- Remove(item);
- }
-
- return removed;
- }
- }
- #endregion
-
- #region ForEach (Public)
- /// <summary>
- /// Performs the specified action on each item in this collection.
- /// </summary>
- /// <param name="action">An Action delegate which is invoked for each item
- /// in this collection.</param>
- public virtual void ForEach(Action<T> action)
- {
- if (action == null)
- {
- throw new ArgumentNullException("action");
- }
-
- foreach (T item in this)
- {
- action(item);
- }
- }
- #endregion
-
- #region ConvertAll (Public)
- /// <summary>
- /// Convert this collection of items by applying a delegate to each item
- /// in the collection. The resulting enumeration contains the result of
- /// applying <paramref name="converter"/> to each item in this collection,
- /// in order.
- /// </summary>
- /// <typeparam name="TOutput">The type each item is being converted to.
- /// </typeparam>
- /// <param name="converter">A delegate to the method to call, passing each
- /// item in this collection.</param>
- /// <returns>An IEnumerable<TOutput^gt; that enumerates the resulting
- /// collection from applying <paramref name="converter"/> to each item in
- /// this collection in order.</returns>
- /// <exception cref="ArgumentNullException"><paramref name="converter"/>
- /// is null.</exception>
- public virtual IEnumerable<TOutput> ConvertAll<TOutput>(
- Converter<T, TOutput> converter)
- {
- if (converter == null)
- {
- throw new ArgumentNullException("converter");
- }
-
- foreach (T sourceItem in this)
- {
- yield return converter(sourceItem);
- }
- }
- #endregion
-
- #region ToString (Public)
- /// <summary>
- /// 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.
- /// </summary>
- /// <returns>The string representation of the collection.</returns>
- public override string ToString()
- {
- return this.Write();
- }
- #endregion
-
- #region Methods (Private)
-
- #region DebuggerToString
- /// <summary>
- /// 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.
- /// </summary>
- /// <returns>The string representation of the items in the collection,
- /// similar in format to ToString().</returns>
- internal string DebuggerToString()
- {
- const int MAXLENGTH = 250;
-
- StringBuilder builder = new 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();
- }
- #endregion
-
- #endregion
- }
-
- /// <summary>
- /// Collection base tests, must be declared outside of a generic class.
- /// </summary>
- internal class CollectionBaseTests
- {
- #region Helpers
-
- #region DerivedCollectionBase
- /// <summary>
- /// Derived collection base
- /// </summary>
- private class DerivedCollectionBase<T> : CollectionBase<T>
- {
- #region Count (Public)
- /// <summary>
- /// Count
- /// </summary>
- /// <returns>Int</returns>
- public override int Count
- {
- get
- {
- return items.Count;
- } // get
- }
- #endregion
-
- #region Private
-
- #region items (Private)
- /// <summary>
- /// Items
- /// </summary>
- private readonly List<T> items;
- #endregion
-
- #endregion
-
- #region Constructors
- /// <summary>
- /// Create derived collection base
- /// </summary>
- /// <param name="setItems">Set items</param>
- public DerivedCollectionBase(T[] setItems)
- {
- items = new List<T>(setItems);
- }
-
- /// <summary>
- /// Create derived collection base
- /// </summary>
- /// <param name="setItems">Set items</param>
- public DerivedCollectionBase(IEnumerable<T> setItems)
- {
- items = new List<T>(setItems);
- }
- #endregion
-
- #region Clear (Public)
- /// <summary>
- /// Clear
- /// </summary>
- public override void Clear()
- {
- items.Clear();
- }
- #endregion
-
- #region Remove (Public)
- /// <summary>
- /// Remove item from the collection.
- /// </summary>
- /// <param name="item">Item</param>
- /// <returns>True if the item was removed</returns>
- public override bool Remove(T item)
- {
- return items.Remove(item);
- }
- #endregion
-
- #region GetEnumerator (Public)
- /// <summary>
- /// Get enumerator
- /// </summary>
- /// <returns>IEnumerator</returns>
- public override IEnumerator<T> GetEnumerator()
- {
- return items.GetEnumerator();
- }
- #endregion
- }
- #endregion
-
- #endregion
-
- #region CheckEnumerableElementsAnyOrder (Static)
- /// <summary>
- /// Test an IEnumerable should contain the given values in any order.
- /// </summary>
- /// <param name="e">E</param>
- /// <param name="expected">Expected</param>
- [Test]
- internal static void CheckEnumerableElementsAnyOrder<T>(
- IEnumerable<T> e, T[] expected)
- {
- bool[] found = new bool[expected.Length];
- int i = 0;
- foreach (T item in e)
- {
- int index;
- for (index = 0; index < expected.Length; ++index)
- {
- if (!found[index] &&
- Equals(expected[index], item))
- {
- break;
- }
- }
- Assert.True(index < expected.Length);
- Assert.True(Equals(expected[index], item));
- found[index] = true;
- ++i;
- }
- Assert.Equal(expected.Length, i);
- }
- #endregion
-
- #region TestCollectionBase (Static)
- /// <summary>
- /// Test collection base. Note: Too slow for a dynamic unit test.
- /// </summary>
- [Test]
- public static void TestCollectionBase()
- {
- string[] testStrings =
- new[]
- {
- "Omg", "what", "the", "f", "is", "up"
- };
-
- DerivedCollectionBase<string> testCollection =
- new DerivedCollectionBase<string>(testStrings);
-
- Assert.Equal("what", testCollection.ToArray()[1]);
- Assert.Equal("the", testCollection.ToArray()[2]);
- Assert.Equal("Omg", testCollection.ToArray()[0]);
-
- Assert.Equal("Omg, what, the, f, is, up", testCollection.ToString());
- }
- #endregion
-
- #region TestExists (Static)
- /// <summary>
- /// Test exists. Note: Too slow for a dynamic unit test.
- /// </summary>
- [Test]
- public static void TestExists()
- {
- DerivedCollectionBase<double> coll1 =
- new DerivedCollectionBase<double>(
- new[]
- {
- 4.5, 1.2, 7.6, -7.6, -0.04, 1.78, 10.11, 187.4
- });
-
- Assert.True(coll1.Exists(
- delegate(double d)
- {
- return d > 100;
- }));
- Assert.True(coll1.Exists(
- delegate(double d)
- {
- return Math.Abs(d) == 0.04;
- }));
- Assert.False(coll1.Exists(
- delegate(double d)
- {
- return d < -10.0;
- }));
- coll1.Clear();
- Assert.False(coll1.Exists(
- delegate(double d)
- {
- return Math.Abs(d) == 0.04;
- }));
-
- DerivedCollectionBase<double> coll2 =
- new DerivedCollectionBase<double>(
- new[]
- {
- 4.5, 1.2, 7.6, -7.6, -0.04, 1.78, 10.11, 187.4
- });
-
- Assert.True(coll2.Exists(
- delegate(double d)
- {
- return d > 100;
- }));
- Assert.True(coll2.Exists(
- delegate(double d)
- {
- return Math.Abs(d) == 0.04;
- }));
- Assert.False(coll2.Exists(
- delegate(double d)
- {
- return d < -10.0;
- }));
- coll2 = new DerivedCollectionBase<double>(new double[]
- {
- });
- Assert.False(coll2.Exists(
- delegate(double d)
- {
- return Math.Abs(d) == 0.04;
- }));
- }
- #endregion
-
- #region TestTrueForAll (Static)
- /// <summary>
- /// Test true for all. Note: Too slow for a dynamic unit test.
- /// </summary>
- [Test]
- public static void TestTrueForAll()
- {
- DerivedCollectionBase<double> coll1 =
- new DerivedCollectionBase<double>(
- new[]
- {
- 4.5, 1.2, 7.6, -7.6, -0.04, 1.78, 10.11, 187.4
- });
-
- Assert.False(coll1.TrueForAll(
- delegate(double d)
- {
- return d > 100;
- }));
- Assert.False(coll1.TrueForAll(
- delegate(double d)
- {
- return Math.Abs(d) < 10;
- }));
- Assert.True(coll1.TrueForAll(
- delegate(double d)
- {
- return d > -10;
- }));
- Assert.True(coll1.TrueForAll(
- delegate(double d)
- {
- return Math.Abs(d) < 200;
- }));
- coll1.Clear();
- Assert.True(coll1.TrueForAll(
- delegate(double d)
- {
- return Math.Abs(d) == 0.04;
- }));
-
- DerivedCollectionBase<double> coll2 =
- new DerivedCollectionBase<double>(
- new[]
- {
- 4.5, 1.2, 7.6, -7.6, -0.04, 1.78, 10.11, 187.4
- });
-
- Assert.False(coll2.TrueForAll(
- delegate(double d)
- {
- return d > 100;
- }));
- Assert.False(coll2.TrueForAll(
- delegate(double d)
- {
- return Math.Abs(d) < 10;
- }));
- Assert.True(coll2.TrueForAll(
- delegate(double d)
- {
- return d > -10;
- }));
- Assert.True(coll2.TrueForAll(
- delegate(double d)
- {
- return Math.Abs(d) < 200;
- }));
- coll2 = new DerivedCollectionBase<double>(new double[]
- {
- });
- Assert.True(coll2.TrueForAll(
- delegate(double d)
- {
- return Math.Abs(d) == 0.04;
- }));
- }
- #endregion
-
- #region TestCountWhere (Static)
- /// <summary>
- /// Test count where. Note: Too slow for a dynamic unit test.
- /// </summary>
- [Test]
- public static void TestCountWhere()
- {
- DerivedCollectionBase<double> coll1 =
- new DerivedCollectionBase<double>(
- new[]
- {
- 4.5, 1.2, 7.6, -7.6, -0.04, 1.78, 10.11, 187.4
- });
-
- Assert.Equal(0, coll1.CountWhere(
- delegate(double d)
- {
- return d > 200;
- }));
- Assert.Equal(6, coll1.CountWhere(
- delegate(double d)
- {
- return Math.Abs(d) < 10;
- }));
- Assert.Equal(8, coll1.CountWhere(
- delegate(double d)
- {
- return d > -10;
- }));
- Assert.Equal(4, coll1.CountWhere(
- delegate(double d)
- {
- return Math.Abs(d) > 5;
- }));
- coll1.Clear();
- Assert.Equal(0, coll1.CountWhere(
- delegate(double d)
- {
- return Math.Abs(d) < 10;
- }));
-
- DerivedCollectionBase<double> coll2 =
- new DerivedCollectionBase<double>(
- new[]
- {
- 4.5, 1.2, 7.6, -7.6, -0.04, 1.78, 10.11, 187.4
- });
-
- Assert.Equal(0, coll2.CountWhere(
- delegate(double d)
- {
- return d > 200;
- }));
- Assert.Equal(6, coll2.CountWhere(
- delegate(double d)
- {
- return Math.Abs(d) < 10;
- }));
- Assert.Equal(8, coll2.CountWhere(
- delegate(double d)
- {
- return d > -10;
- }));
- Assert.Equal(4, coll2.CountWhere(
- delegate(double d)
- {
- return Math.Abs(d) > 5;
- }));
- coll2 = new DerivedCollectionBase<double>(new double[]
- {
- });
- Assert.Equal(0, coll2.CountWhere(
- delegate(double d)
- {
- return Math.Abs(d) < 10;
- }));
- }
- #endregion
-
- #region TestFindAll (Static)
- /// <summary>
- /// Test find all. Note: Too slow for a dynamic unit test.
- /// </summary>
- [Test]
- public static void TestFindAll()
- {
- DerivedCollectionBase<double> coll1 =
- new DerivedCollectionBase<double>(
- new[]
- {
- 4.5, 1.2, 7.6, -0.04, -7.6, 1.78, 10.11, 187.4
- });
- double[] expected = {
- 7.6, -7.6, 10.11, 187.4
- };
- int i;
-
- i = 0;
- foreach (double x in coll1.FindAll(
- delegate(double d)
- {
- return Math.Abs(d) > 5;
- }))
- {
- Assert.Equal(expected[i], x);
- ++i;
- }
- Assert.Equal(expected.Length, i);
-
- DerivedCollectionBase<double> coll2 =
- new DerivedCollectionBase<double>(
- new[]
- {
- 4.5, 1.2, 7.6, -0.04, -7.6, 1.78, 10.11, 187.4
- });
- expected = new[]
- {
- 7.6, -7.6, 10.11, 187.4
- };
-
- i = 0;
- foreach (double x in coll2.FindAll(
- delegate(double d)
- {
- return Math.Abs(d) > 5;
- }))
- {
- Assert.Equal(expected[i], x);
- ++i;
- }
- Assert.Equal(expected.Length, i);
- }
- #endregion
-
- #region TestRemoveAll (Static)
- /// <summary>
- /// Test remove all. Note: Too slow for a dynamic unit test.
- /// </summary>
- [Test]
- public static void TestRemoveAll()
- {
- DerivedCollectionBase<double> coll1 =
- new DerivedCollectionBase<double>(
- new[]
- {
- 4.5, 1.2, 7.6, -0.04, -7.6, 1.78, 10.11, 187.4
- });
-
- coll1.RemoveAll(delegate(double d)
- {
- return Math.Abs(d) > 5;
- });
- CompareCollections(coll1, new[]
- {
- 4.5, 1.2, -0.04, 1.78
- }, true);
-
- coll1 = new DerivedCollectionBase<double>(
- new[]
- {
- 4.5, 1.2, 7.6, -0.04, -7.6, 1.78, 10.11, 187.4
- });
- coll1.RemoveAll(delegate(double d)
- {
- return d == 0;
- });
- CompareCollections(coll1,
- new[]
- {
- 4.5, 1.2, 7.6, -0.04, -7.6, 1.78, 10.11, 187.4
- }, true);
-
- coll1 = new DerivedCollectionBase<double>(
- new[]
- {
- 4.5, 1.2, 7.6, -0.04, -7.6, 1.78, 10.11, 187.4
- });
- coll1.RemoveAll(delegate(double d)
- {
- return d < 200;
- });
- Assert.Equal(0, coll1.Count);
- }
- #endregion
-
- #region TestForEach (Static)
- /// <summary>
- /// Test for each. Note: Too slow for a dynamic unit test.
- /// </summary>
- [Test]
- public static void TestForEach()
- {
- DerivedCollectionBase<string> coll1 =
- new DerivedCollectionBase<string>(
- new[]
- {
- "foo", "bar", "hello", "sailor"
- });
- string s = "";
- coll1.ForEach(delegate(string x)
- {
- s += "!" + x;
- });
- Assert.Equal(s, "!foo!bar!hello!sailor");
-
- DerivedCollectionBase<string> coll2 =
- new DerivedCollectionBase<string>(
- new[]
- {
- "foo", "bar", "hello", "sailor"
- });
- s = "";
- coll2.ForEach(delegate(string x)
- {
- s += "!" + x;
- });
- Assert.Equal(s, "!foo!bar!hello!sailor");
-
- coll1 = new DerivedCollectionBase<string>(new string[]
- {
- });
- s = "";
- coll1.ForEach(delegate(string x)
- {
- s += "!" + x;
- });
- Assert.Equal(s, "");
-
- coll2 = new DerivedCollectionBase<string>(new string[]
- {
- });
- s = "";
- coll2.ForEach(delegate(string x)
- {
- s += "!" + x;
- });
- Assert.Equal(s, "");
- }
- #endregion
-
- #region CompareCollections (LongRunning)
- /// <summary>
- /// Test an ICollection<string> that should contain the given values,
- /// possibly in order. Checks only the following items: GetEnumerator,
- /// CopyTo, Count, Contains.
- /// </summary>
- /// <param name="coll">ICollection to test. </param>
- /// <param name="values">The elements that should be in the collection.
- /// </param>
- /// <param name="mustBeInOrder">Must the elements be in order?</param>
- [Test, Category("LongRunning")]
- public static void CompareCollections<T>(
- ICollection<T> coll, T[] values, bool mustBeInOrder)
- {
- bool[] used = new bool[values.Length];
-
- // Check ICollection.Count.
- Assert.Equal(values.Length, coll.Count);
-
- // Check ICollection.GetEnumerator().
- int i = 0, j;
-
- foreach (T s in coll)
- {
- if (mustBeInOrder)
- {
- Assert.True(Equals(values[i], s));
- } // if (mustBeInOrder)
- else
- {
- bool found = false;
-
- for (j = 0; j < values.Length; ++j)
- {
- if (!used[j] && Equals(values[j], s))
- {
- found = true;
- used[j] = true;
- break;
- } // if ()
- } // for (j)
-
- Assert.True(found);
- } // else
-
- ++i;
- } // foreach
-
- // Check Contains
- foreach (T s in values)
- {
- Assert.True(coll.Contains(s));
- } // foreach
-
- // Check CopyTo.
- used = new bool[values.Length];
-
- T[] newKeys = new T[coll.Count + 2];
-
- coll.CopyTo(newKeys, 1);
- for (i = 0, j = 1; i < coll.Count; ++i, ++j)
- {
- if (mustBeInOrder)
- {
- Assert.True(Equals(values[i], newKeys[j]));
- } // if (mustBeInOrder)
- else
- {
- bool found = false;
-
- for (int k = 0; k < values.Length; ++k)
- {
- if (!used[k] && Equals(values[k], newKeys[j]))
- {
- found = true;
- used[k] = true;
- break;
- } // if ()
- } // for (int)
-
- Assert.True(found);
- } // else
- } // for (i)
-
- // Shouldn't have distubed the values around what was filled in.
- Assert.True(Equals(default(T), newKeys[0]));
- Assert.True(Equals(default(T), newKeys[coll.Count + 1]));
-
- if (coll.Count != 0)
- {
- // Check CopyTo exceptions.
- try
- {
- coll.CopyTo(null, 0);
- throw new Exception("Copy to null should throw exception");
- } // try
- catch (Exception e)
- {
- Assert.True(e is ArgumentNullException);
- } // catch
- try
- {
- coll.CopyTo(newKeys, 3);
- throw new Exception("CopyTo should throw argument exception");
- } // try
- catch (Exception e)
- {
- Assert.True(e is ArgumentException);
- } // catch
- try
- {
- coll.CopyTo(newKeys, -1);
- throw new Exception(
- "CopyTo should throw argument out of range exception");
- } // try
- catch (Exception e)
- {
- Assert.True(e is ArgumentOutOfRangeException);
- } // catch
- } // if (coll.Count)
- }
- #endregion
- }
- }