Кот Матроскин
Поясни:
- что значит "могут не отрабатывать контракт"
- почему input не должен быть decimal
- каким "контрактом на EMA это не регламентировано"
Контракт это соглашение о том какие параметры должны обрабатываться методом или объектом. Все интерфейсы и базовые классы - это своего рода контракты для реализующих их классов. В данном случае линия наследования ExponentialMovingAverage:LengthIndicator, LengthIndicator:BaseIndicator, BaseIndicator:IIndicator показывает, что EMA должен отрабатывать все вызовы, которые присутствуют в IIndicator.
В IIndicator есть Process, который принимает IIndicatorValue. Т.е. любой потомок IIndicator должен обработать все, что есть IIndicatorValue.
Я создаю new CandleIndicatorValue(new TimeFrameCandle...), который по наследования является IIndicatorValue.
Почему при передаче валидного IIndicatorValue в метод Process летит Эксепшен?
Теперь по пунктам:
- при передаче IIndicatorValue в метод Process класса EMA вылетает Эксепшен. ИМХО если метод принимает параметер определенного типа (тип прописан в сигнатуре), то он должен его обработать.
- input может быть IIndicatorValue содержащим decimal, а может быть IIndicatorValue содержащим любой другой тип, который захотел программист.
- IIndicator разрешает любой IIndicatorValue.
Решения с точки зрения программирования:
Если IIndicatorValue должен как то приводиться к decimal, то ИМХО стоит сделать метод public decimal ConvertToDecimal(), где все типы должны приводиться самим создателем наследника от IIndicatorValue.
Если не все IIndicatorValue приводимы к decimal, то ИМХО стоит выделить приводимые к decimal в наследника IIndicatorValue. А методы типа IIndicatorValue Process(IIndicatorValue input); заменить на этого наследника для всех приводимых к decimal типов.
Вероятно, я не до конца понимаю объектную модель индикаторов [biggrin]
Пока смотрел исходники появилась еще одна идея - типизировать сам IIndicator, а в наследниках указывать какие именно типа объектов может принимать Process. Возможно это тоже сможет упростить дело.