Реализация интерфейса, в котором дженерики основаны на интерфейсе - PullRequest
5 голосов
/ 11 мая 2011

В настоящее время я выполняю рефакторинг своего кода, чтобы все важные классы реализовали интерфейс (для тестируемости модулей). Я наткнулся на класс, который реализует IComparable (не шаблонно); что-то вроде:

public MyClass : IComparable
{
    public int CompareTo(object obj)
    {
        MyClass cObj = obj as MyClass;
        if (cObj == null) { throw new ArgumentException(); }
        // etc.
    }
}

Я хочу связать его и использовать дженерики, пока я в нем; как то так:

public IMyClass : IComparable<IMyClass>
{
    // Other methods here
}

public MyClass : IMyClass
{
    public CompareTo<IMyClass>(IMyClass other)
    {
        ...
    }
    // Other methods here
}

Но в идеале MyClass должен реализовывать IComparable<MyClass> (а затем подклассы MyClass должны реализовывать IComparable<MySubClass>).

Все это, чтобы задать несколько вопросов:

Что вы думаете о подходе, который я описал? Есть ли лучший способ сделать этот рефакторинг? Есть ли смысл в том, чтобы MyClass также реализовывал IComparable<MyClass>, или это бессмысленно, поскольку мы уже внедрили IComparable<IMyClass>? Любые про-советы или "лучшие" практики, о которых я мог знать?

Ответы [ 2 ]

2 голосов
/ 11 мая 2011

Имеет ли смысл иметь несколько объектов разных типов, которые сопоставимы друг с другом?Язык позволяет это, но я могу рассчитывать на 0 раз, сколько раз мне пришлось его использовать.

Я бы порекомендовал использовать IClass, не будучи IComparable, и просто иметь производные классыреализовать IComparable.

PS Я также против добавления интерфейсов "для проверки юнитов".Если при разработке вашей программы требуется фабричный шаблон со связью только для интерфейса, то непременно закодируйте этот уровень сложности.Но не стоит злоупотреблять дизайном только для того, чтобы облегчить ваши тесты;используйте вместо этого родинки.

0 голосов
/ 11 мая 2011

Краткий ответ: это зависит.

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

То, какие классы должны реализовывать IComparable, обобщенно или иным образом, полностью зависит от ваших потребностей в сравнении. Если сравнение всегда выполняется между ссылками на базовый класс, производный класс не должен реализовывать интерфейс, так как он никогда не будет вызван.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...