Модифицируемая реализация IComparable?

Если я правильно понимаю, IComparable и IComparable<T> предназначены для определения естественного или полного упорядочения набора типов. В любом случае отношение, определяемое CompareTo(Object) или CompareTo(T), должно быть рефлексивным, симметричным и транзитивным.

Все это очень хорошо и хорошо и вполне применимо, когда применяется к одному типу или даже к целой иерархии типов (предположим, что эти более производные типы не должны влиять на определение отношения). Однако, как только подтип вводит элемент состояния, который должен повлиять на его отношение с точки зрения тех типов, от которых он производен, сравнимые интерфейсы, кажется, почти не работают.

Предоставленный образец кода демонстрирует мое текущее решение проблемы. Поскольку RelationalObject не может иметь каких-либо знаний о тех типах, которые действительно необходимо сравнивать, его основная цель состоит в том, чтобы в первую очередь предоставить и запечатать модифицируемую реализацию CompareTo, требуя, чтобы производные типы фактически реализовывали алгоритмы сравнения на основе контекста.

Мне интересно, есть ли лучший метод обработки таких сценариев? Я понимаю, что, вероятно, мог бы просто реализовать некоторые IComparer или IComparer<T>, которые знают и могут обрабатывать сравнение известных объектов; однако это, кажется, противоречит цели IComparable и 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);
}

person Bradford Fisher    schedule 04.08.2012    source источник
comment
Я думаю, что это был бы хороший кандидат на сайт Code Review.   -  person Brannon    schedule 04.08.2012


Ответы (1)


IComparable<T> в первую очередь предназначен для сравнения объектов одного типа, а не типа и его потомков. Вот почему у вас возникают проблемы с обработкой сравнения неизвестных типов. Поэтому я бы придерживался реализации IComparer.

person Serg Rogovtsev    schedule 04.08.2012
comment
Я уделил этой теме гораздо больше внимания с тех пор, как был опубликован ваш ответ, и полагаю, что на данный момент реализация IComparer и IComparer‹T› по отдельности приведет к более эффективному решению. По этой причине я принимаю этот ответ. Тем не менее, я не могу не задаться вопросом, могут ли некоторые решения быть лучше описаны шаблоном, подобным тому, который был предложен. В любом случае спасибо за отзыв! - person Bradford Fisher; 10.08.2012