次の方法で共有


Have an IComparer but need an IComparable?

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<T> has all of the methods necessary implement IComparer<T>. 

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<T>.  This class can be used wherever an IComparable<T> 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);
        }
    }