/Utilities/Collections/UniqueList.cs
C# | 348 lines | 195 code | 28 blank | 125 comment | 2 complexity | eb8850683e507a72fc6f3136382ce26f MD5 | raw file
Possible License(s): Apache-2.0
- using System.Collections;
- using System.Collections.Generic;
- using Delta.Utilities.Helpers;
- using NUnit.Framework;
-
- namespace Delta.Utilities.Collections
- {
- /// <summary>
- /// Based on simple List<T> generic collection, but this also checks
- /// if elements do already exists. It will not add duplicates, duplicates
- /// are ignored!
- /// </summary>
- /// <typeparam name="T">T</typeparam>
- public class UniqueList<T>
- : IList<T>, ICollection<T>, IEnumerable<T>, IEnumerable,
- ICloneable<UniqueList<T>>
- {
- #region Item (Public)
- /// <summary>
- /// This
- /// </summary>
- /// <param name="index">Index</param>
- /// <returns>T</returns>
- public T this[int index]
- {
- get
- {
- return data[index];
- }
- set
- {
- data[index] = value;
- }
- }
- #endregion
-
- #region Count (Public)
- /// <summary>
- /// Count, returns number of entries in the list
- /// </summary>
- /// <typeparam name="T">T</typeparam>
- /// <returns>Number of entries in the list</returns>
- public int Count
- {
- get
- {
- return data.Count;
- } // get
- }
- #endregion
-
- #region IsReadOnly (Public)
- /// <summary>
- /// Is this list read only? Will always return false.
- /// </summary>
- /// <typeparam name="T">T</typeparam>
- /// <returns>
- /// Will always returns false because this list is never read only
- /// </returns>
- public bool IsReadOnly
- {
- get
- {
- return false;
- } // get
- }
- #endregion
-
- #region Private
-
- #region data (Private)
- /// <summary>
- /// Using List<T>, we can't derive from it to override the methods.
- /// </summary>
- /// <typeparam name="T">T</typeparam>
- private readonly List<T> data = new List<T>();
- #endregion
-
- #endregion
-
- #region Constructors
- /// <summary>
- /// Create unique list
- /// </summary>
- public UniqueList()
- {
- }
-
- /// <summary>
- /// Create unique list
- /// </summary>
- /// <param name="copyFrom">Copy data from this enumerable collection,
- /// if this collection contains multiple same entries, only the first
- /// instances of them will be added (since this is an unique list).
- /// </param>
- public UniqueList(ICollection<T> copyFrom)
- {
- AddRange(copyFrom);
- }
- #endregion
-
- #region ICloneable<UniqueList<T>> Members
- /// <summary>
- /// Clone
- /// </summary>
- public UniqueList<T> Clone()
- {
- return new UniqueList<T>(this);
- }
- #endregion
-
- #region ICollection<T> Members
- /// <summary>
- /// Add
- /// </summary>
- /// <param name="item">Item</param>
- public void Add(T item)
- {
- // Does already exists?
- if (data.IndexOf(item) >= 0)
- {
- // Then don't add again
- return;
- }
- // Else not found, add to list
- data.Add(item);
- }
-
- /// <summary>
- /// Clear
- /// </summary>
- public void Clear()
- {
- data.Clear();
- }
-
- /// <summary>
- /// Contains
- /// </summary>
- /// <param name="item">Item</param>
- /// <returns>True if this list contains the item, false otherwise</returns>
- public bool Contains(T item)
- {
- return data.Contains(item);
- }
-
- /// <summary>
- /// Copy to
- /// </summary>
- /// <param name="array">Array</param>
- /// <param name="arrayIndex">Array index</param>
- public void CopyTo(T[] array, int arrayIndex)
- {
- data.CopyTo(array, arrayIndex);
- }
-
- /// <summary>
- /// Remove
- /// </summary>
- /// <param name="item">Item</param>
- /// <returns>True if the item was removed successfully</returns>
- public bool Remove(T item)
- {
- return data.Remove(item);
- }
- #endregion
-
- #region IEnumerable Members
- /// <summary>
- /// System. collections. i enumerable. get enumerator
- /// </summary>
- /// <returns>System. collections. i enumerator</returns>
- IEnumerator
- IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
- #endregion
-
- #region IEnumerable<T> Members
- /// <summary>
- /// GetEnumerator
- /// </summary>
- /// <returns>IEnumerator</returns>
- public IEnumerator<T> GetEnumerator()
- {
- return data.GetEnumerator();
- }
- #endregion
-
- #region IList<T> Members
- /// <summary>
- /// Index of
- /// </summary>
- /// <param name="item">Item</param>
- /// <returns>Int</returns>
- public int IndexOf(T item)
- {
- return data.IndexOf(item);
- }
-
- /// <summary>
- /// Insert
- /// </summary>
- /// <param name="index">Index</param>
- /// <param name="item">Item</param>
- public void Insert(int index, T item)
- {
- // Does already exists?
- if (data.IndexOf(item) >= 0)
- {
- // Then don't add again
- return;
- // Else not found, add to list
- }
- data.Insert(index, item);
- }
-
- /// <summary>
- /// Remove at
- /// </summary>
- /// <param name="index">Index</param>
- public void RemoveAt(int index)
- {
- data.RemoveAt(index);
- }
- #endregion
-
- #region AddRange (Public)
- /// <summary>
- /// Add range, will just use Add to add all elements.
- /// </summary>
- /// <param name="c">Collection to add</param>
- public void AddRange(ICollection<T> c)
- {
- foreach (T obj in c)
- {
- Add(obj);
- }
- }
- #endregion
-
- #region Sort (Public)
- /// <summary>
- /// Sort list, same as List<T>
- /// </summary>
- /// <param name="comparer">Comparer</param>
- public void Sort(IComparer<T> comparer)
- {
- data.Sort(comparer);
- }
-
- /// <summary>
- /// Sort list, same as List<T>
- /// </summary>
- public void Sort()
- {
- data.Sort();
- }
- #endregion
-
- #region ToArray (Public)
- /// <summary>
- /// To array helper method, very useful to convert generic dynamic list
- /// to simple static list.
- /// </summary>
- /// <returns>Array</returns>
- public T[] ToArray()
- {
- return data.ToArray();
- }
- #endregion
-
- #region ToList (Public)
- /// <summary>
- /// To array helper method, very useful to convert generic dynamic list
- /// to simple static list. Internally this is a list anyway ^^
- /// </summary>
- /// <returns>Array</returns>
- public List<T> ToList()
- {
- return data;
- }
- #endregion
- }
-
- /// <summary>
- /// UniqueList tests, needs to be an extra class because
- /// nesting in generic classes is not supported by NUnit or xUnit.
- /// </summary>
- internal class UniqueListTests
- {
- #region TestUniqueList
- /// <summary>
- /// Test unique list
- /// </summary>
- [Test]
- public void TestUniqueList()
- {
- UniqueList<int> list = new UniqueList<int>();
- list.Add(2);
- list.Add(3);
- list.Add(4);
- list.Add(2);
- Assert.Equal(3, list.Count);
- Assert.Equal(2, list[0]);
- Assert.Equal("2, 3, 4",
- list.Write());
-
- list.Remove(2);
- // 5 does not exists, the following remove will be ignored.
- list.Remove(5);
- Assert.Equal("3, 4",
- list.Write());
-
- int[] intList = list.ToArray();
- Assert.Equal(3, intList[0]);
- Assert.Equal(4, intList[1]);
- Assert.Equal(2, intList.Length);
- }
- #endregion
-
- #region TestConstructor
- /// <summary>
- /// Test the constructor of UniqueList, which should automatically remove
- /// duplicates for us when we pass in an existing list.
- /// </summary>
- [Test]
- public void TestConstructor()
- {
- List<int> listWithDuplicates = new List<int>();
- listWithDuplicates.Add(3);
- listWithDuplicates.Add(5);
- listWithDuplicates.Add(7);
- listWithDuplicates.Add(3);
- UniqueList<int> copiedUniqueList =
- new UniqueList<int>(listWithDuplicates);
- // The original list with duplicates has 4 elements
- Assert.Equal(listWithDuplicates.Count, 4);
- // The unique list should only contain 3 elements (3, 5, and 7)
- Assert.Equal(copiedUniqueList.Count, 3);
- Assert.Equal(copiedUniqueList[0], 3);
- Assert.Equal(copiedUniqueList[1], 5);
- Assert.Equal(copiedUniqueList[2], 7);
- }
- #endregion
- }
- }