PageRenderTime 112ms CodeModel.GetById 60ms app.highlight 23ms RepoModel.GetById 13ms app.codeStats 0ms

/Utilities/Collections/UniqueList.cs

#
C# | 348 lines | 195 code | 28 blank | 125 comment | 2 complexity | eb8850683e507a72fc6f3136382ce26f MD5 | raw file
  1using System.Collections;
  2using System.Collections.Generic;
  3using Delta.Utilities.Helpers;
  4using NUnit.Framework;
  5
  6namespace Delta.Utilities.Collections
  7{
  8	/// <summary>
  9	/// Based on simple List&lt;T&gt; generic collection, but this also checks
 10	/// if elements do already exists. It will not add duplicates, duplicates
 11	/// are ignored!
 12	/// </summary>
 13	/// <typeparam name="T">T</typeparam>
 14	public class UniqueList<T>
 15		: IList<T>, ICollection<T>, IEnumerable<T>, IEnumerable,
 16		  ICloneable<UniqueList<T>>
 17	{
 18		#region Item (Public)
 19		/// <summary>
 20		/// This
 21		/// </summary>
 22		/// <param name="index">Index</param>
 23		/// <returns>T</returns>
 24		public T this[int index]
 25		{
 26			get
 27			{
 28				return data[index];
 29			}
 30			set
 31			{
 32				data[index] = value;
 33			}
 34		}
 35		#endregion
 36
 37		#region Count (Public)
 38		/// <summary>
 39		/// Count, returns number of entries in the list
 40		/// </summary>
 41		/// <typeparam name="T">T</typeparam>
 42		/// <returns>Number of entries in the list</returns>
 43		public int Count
 44		{
 45			get
 46			{
 47				return data.Count;
 48			} // get
 49		}
 50		#endregion
 51
 52		#region IsReadOnly (Public)
 53		/// <summary>
 54		/// Is this list read only? Will always return false.
 55		/// </summary>
 56		/// <typeparam name="T">T</typeparam>
 57		/// <returns>
 58		/// Will always returns false because this list is never read only
 59		/// </returns>
 60		public bool IsReadOnly
 61		{
 62			get
 63			{
 64				return false;
 65			} // get
 66		}
 67		#endregion
 68
 69		#region Private
 70
 71		#region data (Private)
 72		/// <summary>
 73		/// Using List&lt;T&gt;, we can't derive from it to override the methods.
 74		/// </summary>
 75		/// <typeparam name="T">T</typeparam>
 76		private readonly List<T> data = new List<T>();
 77		#endregion
 78
 79		#endregion
 80
 81		#region Constructors
 82		/// <summary>
 83		/// Create unique list
 84		/// </summary>
 85		public UniqueList()
 86		{
 87		}
 88
 89		/// <summary>
 90		/// Create unique list
 91		/// </summary>
 92		/// <param name="copyFrom">Copy data from this enumerable collection,
 93		/// if this collection contains multiple same entries, only the first
 94		/// instances of them will be added (since this is an unique list).
 95		/// </param>
 96		public UniqueList(ICollection<T> copyFrom)
 97		{
 98			AddRange(copyFrom);
 99		}
100		#endregion
101
102		#region ICloneable<UniqueList<T>> Members
103		/// <summary>
104		/// Clone
105		/// </summary>
106		public UniqueList<T> Clone()
107		{
108			return new UniqueList<T>(this);
109		}
110		#endregion
111
112		#region ICollection<T> Members
113		/// <summary>
114		/// Add
115		/// </summary>
116		/// <param name="item">Item</param>
117		public void Add(T item)
118		{
119			// Does already exists?
120			if (data.IndexOf(item) >= 0)
121			{
122				// Then don't add again
123				return;
124			}
125			// Else not found, add to list
126			data.Add(item);
127		}
128
129		/// <summary>
130		/// Clear
131		/// </summary>
132		public void Clear()
133		{
134			data.Clear();
135		}
136
137		/// <summary>
138		/// Contains
139		/// </summary>
140		/// <param name="item">Item</param>
141		/// <returns>True if this list contains the item, false otherwise</returns>
142		public bool Contains(T item)
143		{
144			return data.Contains(item);
145		}
146
147		/// <summary>
148		/// Copy to
149		/// </summary>
150		/// <param name="array">Array</param>
151		/// <param name="arrayIndex">Array index</param>
152		public void CopyTo(T[] array, int arrayIndex)
153		{
154			data.CopyTo(array, arrayIndex);
155		}
156
157		/// <summary>
158		/// Remove
159		/// </summary>
160		/// <param name="item">Item</param>
161		/// <returns>True if the item was removed successfully</returns>
162		public bool Remove(T item)
163		{
164			return data.Remove(item);
165		}
166		#endregion
167
168		#region IEnumerable Members
169		/// <summary>
170		/// System. collections. i enumerable. get enumerator
171		/// </summary>
172		/// <returns>System. collections. i enumerator</returns>
173		IEnumerator
174			IEnumerable.GetEnumerator()
175		{
176			return GetEnumerator();
177		}
178		#endregion
179
180		#region IEnumerable<T> Members
181		/// <summary>
182		/// GetEnumerator
183		/// </summary>
184		/// <returns>IEnumerator</returns>
185		public IEnumerator<T> GetEnumerator()
186		{
187			return data.GetEnumerator();
188		}
189		#endregion
190
191		#region IList<T> Members
192		/// <summary>
193		/// Index of
194		/// </summary>
195		/// <param name="item">Item</param>
196		/// <returns>Int</returns>
197		public int IndexOf(T item)
198		{
199			return data.IndexOf(item);
200		}
201
202		/// <summary>
203		/// Insert
204		/// </summary>
205		/// <param name="index">Index</param>
206		/// <param name="item">Item</param>
207		public void Insert(int index, T item)
208		{
209			// Does already exists?
210			if (data.IndexOf(item) >= 0)
211			{
212				// Then don't add again
213				return;
214				// Else not found, add to list
215			}
216			data.Insert(index, item);
217		}
218
219		/// <summary>
220		/// Remove at
221		/// </summary>
222		/// <param name="index">Index</param>
223		public void RemoveAt(int index)
224		{
225			data.RemoveAt(index);
226		}
227		#endregion
228
229		#region AddRange (Public)
230		/// <summary>
231		/// Add range, will just use Add to add all elements.
232		/// </summary>
233		/// <param name="c">Collection to add</param>
234		public void AddRange(ICollection<T> c)
235		{
236			foreach (T obj in c)
237			{
238				Add(obj);
239			}
240		}
241		#endregion
242
243		#region Sort (Public)
244		/// <summary>
245		/// Sort list, same as List&lt;T&gt;
246		/// </summary>
247		/// <param name="comparer">Comparer</param>
248		public void Sort(IComparer<T> comparer)
249		{
250			data.Sort(comparer);
251		}
252
253		/// <summary>
254		/// Sort list, same as List&lt;T&gt;
255		/// </summary>
256		public void Sort()
257		{
258			data.Sort();
259		}
260		#endregion
261
262		#region ToArray (Public)
263		/// <summary>
264		/// To array helper method, very useful to convert generic dynamic list
265		/// to simple static list.
266		/// </summary>
267		/// <returns>Array</returns>
268		public T[] ToArray()
269		{
270			return data.ToArray();
271		}
272		#endregion
273
274		#region ToList (Public)
275		/// <summary>
276		/// To array helper method, very useful to convert generic dynamic list
277		/// to simple static list. Internally this is a list anyway ^^
278		/// </summary>
279		/// <returns>Array</returns>
280		public List<T> ToList()
281		{
282			return data;
283		}
284		#endregion
285	}
286
287	/// <summary>
288	/// UniqueList tests, needs to be an extra class because
289	/// nesting in generic classes is not supported by NUnit or xUnit.
290	/// </summary>
291	internal class UniqueListTests
292	{
293		#region TestUniqueList
294		/// <summary>
295		/// Test unique list
296		/// </summary>
297		[Test]
298		public void TestUniqueList()
299		{
300			UniqueList<int> list = new UniqueList<int>();
301			list.Add(2);
302			list.Add(3);
303			list.Add(4);
304			list.Add(2);
305			Assert.Equal(3, list.Count);
306			Assert.Equal(2, list[0]);
307			Assert.Equal("2, 3, 4",
308				list.Write());
309
310			list.Remove(2);
311			// 5 does not exists, the following remove will be ignored.
312			list.Remove(5);
313			Assert.Equal("3, 4",
314				list.Write());
315
316			int[] intList = list.ToArray();
317			Assert.Equal(3, intList[0]);
318			Assert.Equal(4, intList[1]);
319			Assert.Equal(2, intList.Length);
320		}
321		#endregion
322
323		#region TestConstructor
324		/// <summary>
325		/// Test the constructor of UniqueList, which should automatically remove
326		/// duplicates for us when we pass in an existing list.
327		/// </summary>
328		[Test]
329		public void TestConstructor()
330		{
331			List<int> listWithDuplicates = new List<int>();
332			listWithDuplicates.Add(3);
333			listWithDuplicates.Add(5);
334			listWithDuplicates.Add(7);
335			listWithDuplicates.Add(3);
336			UniqueList<int> copiedUniqueList =
337				new UniqueList<int>(listWithDuplicates);
338			// The original list with duplicates has 4 elements
339			Assert.Equal(listWithDuplicates.Count, 4);
340			// The unique list should only contain 3 elements (3, 5, and 7)
341			Assert.Equal(copiedUniqueList.Count, 3);
342			Assert.Equal(copiedUniqueList[0], 3);
343			Assert.Equal(copiedUniqueList[1], 5);
344			Assert.Equal(copiedUniqueList[2], 7);
345		}
346		#endregion
347	}
348}