Few months ago I’ve published first version of my ListUnique.
ListUnique is .Net C# generic list which keeps insertion order, you can iterate through it and it has only unique values, with IListUnique interface.
Below is next version, with unit tests.
What’s new :
- new methods AddUniqueOnly & AddRangeUniqueOnly – those methods will add only unique values, won’t throw exception if value is already in list.
Just add unique values and omit existing ones.
This post is also online test of SyntaxHighlighter.
I’ve integrated it with DotNetNuke Blog module.
Within few days I’ll release this module (called BlogPlus) – it contains fixes & modifications & new features for core Blog module, SyntaxHighlighter is one of new features.
using System;
using System.Collections.Generic;
namespace TM.Common.Collections
{
/// <summary>
/// List that allows only unique values
/// </summary>
/// <typeparam name="T">Must implement IComparable T </typeparam>
public class ListUnique<T> : List<T>, IListUnique<T> where T : IComparable<T>
{
public new void Add(T item)
{
if( Exists(itemList => itemList.CompareTo(item) == 0) )
{
throw new ArgumentException("Cannot add not unique value to collection");
}
base.Add(item);
}
/// <summary>
/// Adds element only if is unique
/// </summary>
/// <param name="item"></param>
/// <returns>Return added or not</returns>
public bool AddUniqueOnly(T item)
{
if( Exists(itemList => itemList.CompareTo(item) == 0) )
return false;
base.Add(item);
return true;
}
/// <summary>
/// Adds elements of the specified collection to the end of the list
/// </summary>
/// <param name="coll"></param>
public new void AddRange(IEnumerable<T> coll)
{
foreach (T item in coll)
{
Add(item);
}
}
/// <summary>
/// Adds only unique elements of the specified collection to the end of the list
/// </summary>
/// <param name="coll"></param>
public void AddRangeUnique(IEnumerable<T> coll)
{
foreach (T item in coll)
{
try
{
Add(item);
}
catch (ArgumentException)
{ }
}
}
public List<T> ToList()
{
return this;
}
public ListUnique(IEnumerable<T> collection)
{
foreach (T t in collection)
{
Add(t);
}
}
public ListUnique(int capacity): base(capacity)
{
}
public ListUnique()
{
}
}
/// <summary>
/// IList that allows only unique values
/// </summary>
/// <typeparam name="T">Must implement IComparable T </typeparam>
public interface IListUnique<T> : IList<T> where T : IComparable<T>
{
List<T> ToList();
bool AddUniqueOnly(T item);
/// <summary>
/// Adds elements of the specified collection to the end of the list, throws exception on unique violation
/// </summary>
/// <param name="coll"></param>
void AddRange(IEnumerable<T> coll);
/// <summary>
/// Adds only unique elements of the specified collection to the end of the list
/// </summary>
/// <param name="coll"></param>
void AddRangeUnique(IEnumerable<T> coll);
}
}
And Unit tests:
using System;
using System.Collections.Generic;
using NUnit.Framework;
namespace TM.Common.Collections.Tests
{
[TestFixture]
public class ListUnique_Test
{
[Test]
public void CreateNew()
{
IListUnique<string> listUnique = new ListUnique<string>();
}
[Test]
public void AddUniqueValues()
{
IListUnique<string> listUnique = new ListUnique<string>();
listUnique.Add("a");
listUnique.Add("b");
listUnique.Add("c");
listUnique.Add("d");
Assert.AreEqual(4,listUnique.Count);
Assert.AreEqual("a",listUnique[0]);
Assert.AreEqual("d", listUnique[3]);
}
[Test]
public void AddUniqueOnly_Basic()
{
IListUnique<int> listUnique = new ListUnique<int>();
listUnique.AddUniqueOnly(1);
listUnique.AddUniqueOnly(2);
listUnique.AddUniqueOnly(3);
listUnique.AddUniqueOnly(4);
bool addStatus;
addStatus=listUnique.AddUniqueOnly(3);
Assert.IsFalse(addStatus);
Assert.AreEqual(4,listUnique.Count);
}
[Test]
public void AddRangeUnique()
{
List<string> list = new List<string>();
list.Add("a");
list.Add("b");
list.Add("c");
list.Add("d");
IListUnique<string> listUnique = new ListUnique<string>();
listUnique.AddRange(list);
Assert.AreEqual(4, listUnique.Count);
Assert.AreEqual("a", listUnique[0]);
Assert.AreEqual("d", listUnique[3]);
}
[Test]
[ExpectedException(typeof(ArgumentException))]
public void AddRangeNotUnique_ExceptionExpected()
{
List<string> list;
list = new List<string>();
list.Add("a");
list.Add("b");
list.Add("c");
list.Add("d");
IListUnique<string> listUnique = new ListUnique<string>();
listUnique.AddRange(list);
list = new List<string>();
list.Add("e");
list.Add("f");
list.Add("a"); // <- not unique
list.Add("h");
listUnique.AddRange(list); // <- exception expected
}
[Test]
public void AddRangeUnique_NotUnique()
{
List<string> list;
list = new List<string>();
list.Add("a");
list.Add("b");
list.Add("c");
list.Add("d");
IListUnique<string> listUnique = new ListUnique<string>();
listUnique.AddRange(list);
list = new List<string>();
list.Add("e");
list.Add("f");
list.Add("a"); // <- not unique
list.Add("h");
listUnique.AddRangeUnique(list);
Assert.AreEqual( 7 ,listUnique.Count);
Assert.AreEqual("a", listUnique[0]);
Assert.AreEqual("d", listUnique[3]);
Assert.AreEqual("h", listUnique[6]);
}
[Test]
public void CreateFromUniqueList()
{
List<string> list=new List<string>();
list.Add("a");
list.Add("b");
list.Add("c");
list.Add("d");
IListUnique<string> listUnique = new ListUnique<string>(list);
Assert.AreEqual(4, listUnique.Count);
Assert.AreEqual("a", listUnique[0]);
Assert.AreEqual("d", listUnique[3]);
}
[Test]
[ExpectedException(typeof(ArgumentException))]
public void AddNonUnique()
{
IListUnique<string> listUnique = new ListUnique<string>();
listUnique.Add("a");
listUnique.Add("b");
listUnique.Add("b");
listUnique.Add("d");
Assert.AreEqual(3, listUnique.Count);
Assert.AreEqual("a", listUnique[0]);
Assert.AreEqual("d", listUnique[2]);
}
[Test]
[ExpectedException(typeof(ArgumentException))]
public void CreateFromNotUniqueList()
{
List<string> list = new List<string>();
list.Add("a");
list.Add("b");
list.Add("b");
list.Add("d");
IListUnique<string> listUnique = new ListUnique<string>(list);
Assert.AreEqual(3, listUnique.Count);
Assert.AreEqual("a", listUnique[0]);
Assert.AreEqual("d", listUnique[2]);
}
}
}