Use set operators in C#

[set operators]

This example shows how you can add set operators to make working with sets slightly easier. The example Perform set operations in C# explains how to use the HashSet class to represent and manipulate sets. Unfortunately to manipulate the sets you need to use methods such as IntersectWith, UnionWith, and SymmetricExceptWith instead of more intuitive set operators such as &, |, and ^.

This example shows how to override those operators to make set operations easier.

To override these operators, you need to add code to the class. You might like to add code by using the partial keyword but that only works if every other piece of the class uses the keyword, and Microsoft’s HashSet class doesn’t use that keyword. In other words, you cannot add code to the existing class that way.

To work around this problem, this example derives a Set class that inherits from HashSet. This also lets me use the slightly more intuitive class name Set.

The following code shows the complete Set class.

public class Set<T> : HashSet<T>
{
    // Constructors.
    public Set()
        : base()
    {
    }
    public Set(IEnumerable<T> enumerable)
        : base(enumerable)
    {
    }
    public Set(IEqualityComparer<T> comparer)
        : base(comparer)
    {
    }
    public Set(IEnumerable<T> enumerable, IEqualityComparer<T> comparer)
        : base(enumerable, comparer)
    {
    }

    // Union.
    public static Set<T> operator |(Set<T> A, Set<T> B)
    {
        Set<T> result = new Set<T>(A);
        result.UnionWith(B);
        return result;
    }

    // Intersection.
    public static Set<T> operator &(Set<T> A, Set<T> B)
    {
        Set<T> result = new Set<T>(A);
        result.IntersectWith(B);
        return result;
    }

    // Xor.
    public static Set<T> operator ^(Set<T> A, Set<T> B)
    {
        Set<T> result = new Set<T>(A);
        result.SymmetricExceptWith(B);
        return result;
    }

    // Subset.
    public static bool operator <(Set<T> A, Set<T> B)
    {
        return A.IsSubsetOf(B);
    }

    // Superset.
    public static bool operator >(Set<T> A, Set<T> B)
    {
        return A.IsSupersetOf(B);
    }

    // Contains element.
    public static bool operator >(Set<T> A, T element)
    {
        return A.Contains(element);
    }

    // Consists of a single element.
    public static bool operator <(Set<T> A, T element)
    {
        return (A > element) && (A.Count == 1);
    }
}

The class starts with constructors that simply invoke the base class’s constructors. These are needed so the main program can create a Set and so the operators can create new Set objects.

The binary (two operand) union, intersection, and XOR operators copy the first operand and then use the appropriate HashSet method to combine the copy with the second set.

The subset and superset operators simply invoke the HashSet class’s IsSubsetOf and IsSupersetOf methods.

The “contains element” and “equals element” operators determine whether the set contains an element and whether it contains only the element. I would probably omit the second of these but the operators come in pairs so if you override the > operator then you must also override the < operator. (Alternatively you could have < throw an exception.)


Download Example   Follow me on Twitter   RSS feed   Donate




This entry was posted in algorithms, classes, mathematics and tagged , , , , , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *