Question

If I understand correctly, IComparable and IComparable<T> are intended to allow for the definition of a natural or total ordering over a set of types. In either case, the relation defined by CompareTo(Object) or CompareTo(T) must be Reflexive, Symmetric, and Transitive.

This is all very good and well and quite applicable when applied to a single type or even an entire hierarchy of types (supposing those more derived types do not need to influence the definition of relation). However, once a subtype introduces an element of state which should affect its relation in terms of those types from which it derived, the comparable interfaces almost seem to break down.

The provided code sample demonstrates my current solution to the problem. Because RelationalObject cannot have any knowledge of those types which actually need to be compared, its intended purpose is primarily to provide and seal a modifiable implementation of CompareTo while requiring derived types to actually implemented the comparison algorithms based upon context.

I'm wondering, is there a better method of handling such scenarios? I realize I could probably just implement some IComparer or IComparer<T> which knows about and can handle the comparison of known objects; however, this seems to defeat the purpose of IComparable and IComparable<T>.

using System;

public abstract class RelationalObject : IComparable<RelationalObject>
{
    public sealed int CompareTo(RelationalObject that)
    {
        int relation = 0;

        if (that == null)
            relation = 1;

        if (relation == 0 && !this.Equals(that))
        {
            Type thisType = this.GetType();
            Type thatType = that.GetType();

            if (thatType.IsInstanceOfType(this))
            {
                if (thisType.Equals(thatType))
                    relation = this.CompareToExactType(that);
                else
                    relation = -1 * that.CompareToSuperType(this);
            }
            else
            {
                if (thisType.IsInstanceOfType(that))
                    relation = this.CompareToSuperType(that);
                else
                    relation = this.CompareToForeignType(that);
            }
        }

        return relation;
    }

    protected abstract int CompareToExactType(RelationalObject that);

    protected abstract int CompareToForeignType(RelationalObject that);

    protected abstract int CompareToSuperType(RelationalObject that);
}
Was it helpful?

Solution

IComparable<T> is primarily intended for comparison of objects of one type, not type and its descendants. That's why you're having problems with handling comparison of unknown types. So I'd stick with implementing IComparer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top