C# Generics are powerful, but there are not many generic classes beyond List and Dictionary. Especially for Set Operations Generics are missing.
That’s whay I created a small class for Set Operations called Set that contains the basic Set Operations, like Union, Intersect and Difference.
Here’s a small example how to use it:
public enum DataSource
{
Database, XML, File, Stream, Http, Ftp
}static void Main(string[] args)
{
Set<DataSource> firstSet = new Set<DataSource>(
DataSource.Database, DataSource.File, DataSource.XML);
Set<DataSource> secondSet = new Set<DataSource>(
DataSource.Http, DataSource.Ftp, DataSource.Stream, DataSource.XML, DataSource.File);
Set<DataSource> union = firstSet.Union(secondSet);
// result = Database, File, Xml, Http, Ftp, Stream
Set<DataSource> intersect = firstSet.Intersect(secondSet);
// result = Xml, File
Set<DataSource> difference = firstSet.Difference(secondSet);
// result = Http, Ftp, Stream
}
And below you’ll find the complete implementation.
Cheers
- Gerhard
using System.Collections;
using System.Collections.Generic;
namespace SetExample
{
/// <summary>
/// Set class
/// </summary>
/// <typeparam name="TElement"></typeparam>
public class Set<TElement> : ICollection<TElement>
{
private List<TElement> internalList = new List<TElement>();
/// <summary>
/// Initializes a new instance of the <see cref="Set<TElement>"/> class.
/// </summary>
public Set()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="Set<TElement>"/> class.
/// </summary>
/// <param name="elements">The elements.</param>
public Set(params TElement[] elements)
{
AddRange(elements);
}
/// <summary>
/// Adds the range.
/// </summary>
/// <param name="range">The range.</param>
public void AddRange(IEnumerable<TElement> range)
{
foreach (TElement element in range)
Add(element);
}
/// <summary>
/// Unions the specified set.
/// </summary>
/// <param name="set">The set.</param>
/// <returns></returns>
public Set<TElement> Union(Set<TElement> set)
{
Set<TElement> result = new Set<TElement>();
result.AddRange(this);
result.AddRange(set);
return result;
}
/// <summary>
/// Intersects the specified set.
/// </summary>
/// <param name="set">The set.</param>
public Set<TElement> Intersect(Set<TElement> set)
{
Set<TElement> result = new Set<TElement>();
foreach (TElement element in set)
if (Contains(element))
result.Add(element);
return result;
}
/// <summary>
/// Differences the specified set.
/// </summary>
/// <param name="set">The set.</param>
/// <returns></returns>
public Set<TElement> Difference(Set<TElement> set)
{
Set<TElement> result = new Set<TElement>();
foreach (TElement element in set)
if (!Contains(element))
result.Add(element);
return result;
}
/// <summary>
/// Gets or sets the <see cref="TElement"/> at the specified index.
/// </summary>
/// <value></value>
public TElement this[int index]
{
get { return internalList[index]; }
set { internalList[index] = value; }
}
#region ICollection<TElement> Members
public void Add(TElement item)
{
if (!Contains(item))
internalList.Add(item);
}
public void Clear()
{
internalList.Clear();
}
public bool Contains(TElement item)
{
return internalList.Contains(item);
}
public void CopyTo(TElement[] array, int arrayIndex)
{
internalList.CopyTo(array, arrayIndex);
}
public bool Remove(TElement item)
{
return internalList.Remove(item);
}
public int Count
{
get { return internalList.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
#endregion
#region IEnumerable<TElement> Members
IEnumerator<TElement> IEnumerable<TElement>.GetEnumerator()
{
return internalList.GetEnumerator();
}
#endregion
#region IEnumerable Members
public IEnumerator GetEnumerator()
{
return internalList.GetEnumerator();
}
#endregion
}
}
October 17, 2007 at 9:32 am
Did you try out NGenerics? They contain lots of the features that are missing from System.Collections.Generics
October 17, 2007 at 3:09 pm
NHibernate comes with an assembly call Iesi.Collections, which contains a number of different implementations of ISet. If you just want a set, then surely that’d do it?
October 17, 2007 at 5:58 pm
The free PowerCollections library also has a set.
.NET 3.5 has a generic HashSet collection.
October 21, 2007 at 11:16 pm
[...] is a good article on Set Operations with C# Generics by Gerhard [...]
August 18, 2008 at 4:27 am
Short, clear and straight implementation. Its nice filling .NET gaps.
September 19, 2008 at 1:27 pm
Thanks,
I was missing this!
Very useful.
You could add implementation of symmetric difference.
And the fastest way to compute it, is not the union minus the intersection by the way.
May 13, 2011 at 7:40 pm
Nice, thanks!
October 17, 2011 at 2:38 pm
hi i find your code very useful but when i debug it says its not designed can u please show the tutorial on how to place the buttons and text boxes i would be great full…my email is urbanstyle_92@hotmail.com waiting your reply