Previously we discussed the opposite problem. This is a lesser but often more frustrating problem because there is no, AFAIK, built in solution for the BCL. However it’s problem that can be solved once and reused with a generic solution. IComparable has all of the methods necessary implement IComparer.

To work around this we’ll create a new class that can wrap both a value and an instance of IComparable(Of T). Lets call it ComparerNode. This class can be used wherever an IComparable is needed.

Unfortunately generic classes will not provide a 1:1 mapping. However getting to the actual data is strongly typed and comes through a simple property.

public sealed class ComparerNode<T> : IComparable<ComparerNode<T>> {
    private readonly IComparer<T> m_comparer;
    private readonly T m_value;

    public IComparer<T> Comparer {
        get { return m_comparer; }
    }

    public T Value {
        get { return m_value; }
    }

    public ComparerNode(IComparer<T> comparer, T value) {
        if (comparer == null) {
            throw new ArgumentNullException("comparer");
        }

        m_comparer = comparer;
        m_value = value;
    }

    public override int GetHashCode() {
        if (m_value == null) {
            return 0;
        }

        return m_value.GetHashCode();
    }

    public override bool Equals(object obj) {
        var other = obj as ComparerNode<T>;
        if (other == null) {
            return false;
        }

        return 0 == m_comparer.Compare(m_value, other.m_value);
    }

    #region IComparable<ComparerNode<T>> Members

    public int CompareTo(ComparerNode<T> other) {
        if (other == null) {
            return 1;
        }

        return m_comparer.Compare(m_value, other.m_value);
    }

    #endregion

    public static bool operator <(ComparerNode<T> left, ComparerNode<T> right) {
        return Comparer<ComparerNode<T>>.Default.Compare(left, right) < 0;
    }

    public static bool operator >(ComparerNode<T> left, ComparerNode<T> right) {
        return Comparer<ComparerNode<T>>.Default.Compare(left, right) > 0;
    }

    public static bool operator ==(ComparerNode<T> left, ComparerNode<T> right) {
        return EqualityComparer<ComparerNode<T>>.Default.Equals(left, right);
    }

    public static bool operator !=(ComparerNode<T> left, ComparerNode<T> right) {
        return !EqualityComparer<ComparerNode<T>>.Default.Equals(left, right);
    }
}

public static class ComparerNode {
    public static ComparerNode<T> Create<T>(IComparer<T> comparer, T value) {
        return new ComparerNode<T>(comparer, value);
    }

    public static ComparerNode<T> Create<T>(T value)
        where T : IComparable<T> {
        return new ComparerNode<T>(Comparer<T>.Default, value);
    }
}

Share Post

Google+

comments powered by Disqus