Как наследовать универсальный класс от вложенного универсального класса в C#

Я делал свою домашнюю работу и застрял в некоторых проблемах с дженериками и наследованием.

У меня есть общий класс красно-черного дерева, так как это красно-черное дерево, его ключи должны быть сопоставимы, поэтому

public class RedBlackTree<T> where T : IComparable<T>

И затем я хочу другой класс, скажем, интервальное дерево, которое является расширенной версией красно-черного дерева. Итак, я определил интервал следующим образом:

public class Interval<T> : IComparable where T : IComparable<T>

и так как дерево интервалов действительно является красно-черным деревом с интервалами в качестве ключей, но только с более конкретными методами, я определил класс следующим образом:

public class IntervalTree<T> : RedBlackTree<Interval<T>> where T : IComparable<T>

Но это не позволит мне сделать это, он говорит что-то вроде "не может неявно преобразовать Interval<T> в System.IComparable<Interval<T>>", но я тоже не могу написать что-то вроде where Interval<T> : IComparable<Interval<T>>,

Как бы я делал такие вещи в C#, или если нет способа сделать это наследование в C#, какие другие шаблоны я должен использовать?

2 ответа

Решение

Давайте разберем это. Мы прекратим использовать T для всего, потому что это сбивает с толку.

class RedBlackTree<RBTValue> where RBTValue : IComparable<RBTValue>

ОК, так что каждое RBTValue, которое используется для создания RedBlackTree<> должен быть IComparable<RBTValue>,

Вы хотите сказать

 RedBlackTree<Interval<T>>

для некоторых T в какой-то момент. Что мы тогда знаем? Interval<T> используется для RBTValue, и поэтому Interval<T> должно быть известно, что IComparable<Interval<T>>,

Поэтому определение Interval<> должно быть:

class Interval<IValue> : IComparable<Interval<IValue>>

Теперь, это также тот случай, когда любой IValue должно быть IComparable<IValue>? Если да, то нам нужно ограничение:

class Interval<IValue> : IComparable<Interval<IValue>> 
where IValue : IComparable<IValue>

Убедитесь, что это ясно. Это говорит о двух вещах: (1) что интервал сопоставим с другим интервалом, и (2) что значения в интервале сопоставимы с другими значениями.

Теперь мы хотим определить интервальное дерево.

class IntervalTree<ITValue> : RedBlackTree<Interval<ITValue>>
where ITValue : IComparable<ITValue>

Удовлетворяет ли это наши потребности? Interval<IValue> требует, чтобы IValue воплощать в жизнь IComparable<IValue>, ITValue инвентарь IComparable<ITValue> через ограничение, поэтому требование выполнено.

RedBlackTree<RBTValue> требует, чтобы RBTValue быть IComparable<RBTValue>, Interval<ITValue> инвентарь IComparable<Interval<ITValue>>так что это тоже хорошо, и мы все готово.

Это все говорит: вы могли бы рассмотреть вместо реализации IntervalTree<> с RBT в качестве члена, а не в качестве базового класса. Был ли когда-нибудь случай, когда вы будете полиморфно обрабатывать интервальные деревья с помощью красных черных деревьев? Если нет, то нет необходимости раскрывать детали реализации на публичной поверхности.

Наконец, такие типы могут быть очень запутанными. Чтобы узнать больше о том, каким образом можно использовать этот шаблон гораздо более ужасно, см.

https://blogs.msdn.microsoft.com/ericlippert/2011/02/03/curiouser-and-curiouser/

Вы получаете следующую ошибку:

Ошибка компиляции (строка xx, col yy): тип "Program.Interval" нельзя использовать в качестве параметра типа "T" в универсальном типе или методе "Program.RedBlackTree". Не существует неявного преобразования ссылок из 'Program.Interval' в 'System.IComparable>'.

Вам нужно разобрать ошибку и подумать о том, что она говорит вам. В этом случае вы заявляете, что IntervalTree наследуется от RedBlackTree<Interval<T>>, Тем не менее, вы указали, что общий T тип для RedBlackTree должен реализовать IComparable<T>, Если вы реализуете IComparable за Interval ошибка исчезнет. Interval должен реализовывать интерфейс, используемый для ограничения RedBlackTree,

Другие вопросы по тегам