Нужна помощь в понимании этой иерархии наследования

108
6

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

Все это является частью внутренней работы стека служб WCF, обработки запросов, ответов и т.д.

Я включил в качестве примера только сигнатуры классов и их конструкторы, поскольку внутренняя функциональность не имеет значения.

public sealed class ProcessDerived : ProcessBase<Filter, RequestExternal, RequestItemExternal, ResponseCallBack, ResponseInternal>
{
public ProcessDerived(ProcessManager Manager) : base(Manager) { }
}

public abstract class ProcessBase<TFilter, TRequestExternal, TRequestItemExternal, TResponseCallBack, TResponseInternal>
: ProcessBaseSync<TFilter, TRequestExternal, TRequestItemExternal, TResponseCallBack, TResponseInternal>
where TFilter : FilterBase
where TRequestExternal : class
where TRequestItemExternal : class
where TResponseCallBack : class
where TResponseInternal : ProcessResponseBase
{
protected ProcessBase(ProcessManager Manager) : base(Manager) { }
}

public abstract class ProcessBaseSync<TFilter, TRequestExternal, TRequestItemExternal, TResponseCallBack, TResponseInternal>
: ProcessBaseCache<TFilter, TRequestExternal, TRequestItemExternal, object, TResponseCallBack, TResponseInternal, CacheKeyBase>
where TFilter : FilterBase
where TRequestExternal : class
where TRequestItemExternal : class
where TResponseCallBack : class
where TResponseInternal : ProcessResponseBase
{
protected ProcessBaseSync(ProcessManager Manager) : base(Manager) { }
}

public abstract class ProcessBaseCache<TFilter, TRequestExternal, TRequestItemExternal, TResponseImmediate, TResponseCallBack, TResponseInternal, TCacheKey>
: IProcess, IProcess<TFilter, TResponseInternal>, IProcess<TResponseCallBack>
where TFilter : FilterBase
where TRequestExternal : class
where TRequestItemExternal : class
where TResponseImmediate : class
where TResponseCallBack : class
where TResponseInternal : ProcessResponseBase
where TCacheKey : CacheKeyBase
{
private ProcessManager _manager;

protected ProcessBaseCache(ProcessManager Manager)
{
_manager = Manager;
}
}

Основные вопросы, которые у меня есть:

1) Какой технический термин используется для описания этой структуры множественного наследования, как показано в первой строке: "ProcessDerived: ProcessBase".

Это напоминает мне кортежи, но я не понимаю, что происходит здесь на техническом уровне. Это просто способ обойти ограничение множественного наследования?

2) Он наследует от "ProcessBase", а также от всех параметров типа рядом с ним?

3) Какова цель добавления ": base (XYZ)" в конструктор? Это просто требование соответствия наследования классов (конструктор, имитирующий сигнатуру класса)? Я не понимаю, почему это требуется.

Эта сложная 4-уровневая иерархия кажется очень ненужной и кажется невозможной для подражания.

Я явно упускаю некоторые фундаментальные знания С# здесь.

спросил(а) 2019-02-08T15:04:00+03:00 1 год, 10 месяцев назад
1
Решение
119

1) Какой технический термин используется для описания этой структуры множественного наследования, как показано в первой строке: "ProcessDerived: ProcessBase.

Это единственное наследство. ProcessDerived наследуется от ProcessBase<Filter, RequestExternal, RequestItemExternal, ResponseCallBack, ResponseInternal>.

2) Он наследует от "ProcessBase", а также от всех параметров типа рядом с ним?

ProcessBase<Filter, RequestExternal, RequestItemExternal, ResponseCallBack, ResponseInternal> является (закрытым универсальным) типом. ProcessDerived наследуется от него.

ProcessBase<TFilter, TRequestExternal, TRequestItemExternal, TResponseCallBack, TResponseInternal> - это соответствующий открытый универсальный тип - параметры типа TFilter т.д. Еще не определены.

3) Какова цель добавления ": base (XYZ)" в конструктор? Это просто требование соответствия наследования классов (конструктор, имитирующий сигнатуру класса)? Я не понимаю, почему это требуется.

Когда создается экземпляр вашего подкласса, он должен вызывать один из конструкторов базового класса. Если базовый класс имеет конструктор без параметров, он вызывается неявно. Если это не так, вам нужно явно вызвать один из его конструкторов, передав все необходимые параметры, используя : base(...).

Я явно упускаю некоторые фундаментальные знания С# здесь.

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

ответил(а) 2019-02-08T15:10:00+03:00 1 год, 10 месяцев назад
59

Чтобы ответить на ваш первый (и второй) вопрос, вы можете расширить один базовый класс, а затем реализовать несколько интерфейсов, но размещенный вами код расширяет только один базовый класс. Бывает, что ProcessBase принимает 5 разных типов, но это все еще один класс.

Что касается вашего третьего вопроса, они добавили base потому что класс расширяет базовый класс, у которого нет конструктора без параметров.

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

public class Person
{
public string Name { get; set; }

public Person(string name)
{
Name = name;
}
}

public class Employee : Person
{
public DateTime HireDate { get; set; }

public Employee(string name, DateTime hireDate) : base(name)
{
HireDate = hireDate;
}
}

ответил(а) 2019-02-08T15:11:00+03:00 1 год, 10 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема