Set Operations with C# Generics

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

kick it on DotNetKicks.com



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&lt;TElement&gt;"/> class.
        /// </summary>
        public Set()
        {
            
        }
        
        /// <summary>
        /// Initializes a new instance of the <see cref="Set&lt;TElement&gt;"/> 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
    }
}

About these ads

8 Responses to “Set Operations with C# Generics”

  1. Niki Says:

    Did you try out NGenerics? They contain lots of the features that are missing from System.Collections.Generics

  2. B3ardman Says:

    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?

  3. Judah Says:

    The free PowerCollections library also has a set.

    .NET 3.5 has a generic HashSet collection.

  4. Weekly Link Post 12 « Rhonda Tipton’s WebLog Says:

    [...] is a good article on Set Operations with C# Generics by Gerhard [...]

  5. Rahul Says:

    Short, clear and straight implementation. Its nice filling .NET gaps.

  6. Hugo Says:

    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.

  7. Mido Says:

    Nice, thanks!

  8. nader khatib Says:

    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


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 106 other followers

%d bloggers like this: