Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Please make ISeries<T> covariant

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Please make ISeries<T> covariant

    I'm having to jump through a lot of hoops to work around this.

    #2
    Hello,

    Thank you for your suggestion. Can you please describe the benefits that would be conveyed by this change, or exactly what is getting in the way without this change, so that we can fully understand the use-case behind the suggestion?
    Dave I.NinjaTrader Product Management

    Comment


      #3
      Thanks Dave!

      Sure, no problem. The scenario I'm currently working on actually has two issues: 1) Need to lazily assign the values of a series, 2) Need to substitute the type of data provided by the series.

      I have already submitted a request for item 1 - http://ninjatrader.com/support/forum...ad.php?t=79297.

      Scenario:
      • I have a class, BarInfo, that stores attributes about a bar.
      • I have a class, HeikenBarInfo - which descends from BarInfo, that stores attributes about a bar based on Heiken Ashi.
      • I have a BarInfoSeries property (BarInfo) on Indicator.
      • I have a derived Indicator class, IndicatorWithHeiken (base class for indicators that use Heiken Ashi), that has a BarInfoSeries property (HeikenBarInfo).


      NOTES:
      • Not all derived indicators (certainly not the stock indicators) are going to use the BarInfo property on Indicator so the series should not calculate values unless it is requested (the lazy part).
      • The IndicatorWithHeiken class adds it's own BarInfoSeries property (HeikenBarInfo) but it also needs to set that as the inherited BarInfo property so the values aren't being calculated multiple times. It can't do this because ISeries<BarInfo> is not covariant.


      It may seem a little more complicated than it actually is. Hopefully the code below will clarify and simplify a bit.

      This is the goal:
      Code:
      public class BarInfo
      {
          public int BarIdx { get; private set; }
          public bool IsUp { get; private set }
      }
      
      public class HeikenBarInfo : BarInfo
      {
          public bool IsHeikenUp { get; private set }
      }
      
      public partial class Indicator
      {
          [Browsable(false), XmlIgnore]
          public ISeries<BarInfo> BarInfo { get; protected set; }
      
          protected override void OnStateChange()
          {
              if (State == State.Configure)
                  BarInfo = new BarInfoSeries(this);
          }
      }
      
      public class IndicatorWithHeiken : Indicator
      {
          [Browsable(false), XmlIgnore]
          public ISeries<HeikenBarInfo> HeikenBarInfo { get; protected set; }
      
          protected override void OnStateChange()
          {
              if (State == State.Configure)
              {
                  HeikenBarInfo = new HeikenBarInfoSeries(this);
                  [COLOR="SeaGreen"]// Assign the regular property to the Heiken one so there is only one series
                  // and calculations are only done once.[/COLOR]
                  BarInfo = HeikenBarInfo; [B]<<< --- can't do this because not covariant![/B]
              }
          }
      }
      As you can see, the code is pretty simple and straightforward. In order to to work around the issue, I have to introduce more layers:
      • Decorator pattern: Create a VirtualSeries<T> class that decorates Series<T> allowing overriding the properties and methods. Allows for lazy calculation of values.
      • Adapter pattern: Create a new IVirtualSeries<out T> interface in order to have covariance. Cannot inherit ISeries<T> because of C# rules on variance. VirtualSeries<T> implements both ISeries<T> and IVirtualSeries<T>.

      Now the code changes to use IVirtualSeries<T> for the properties instead of ISeries<T> and everything works fine. The problem is all the new classes and interfaces and additional layers of indirection that unnecessarily complicate the code. It can all be avoided by having the Series<T> properties and methods virtual and by changing ISeries<T> to ISeries<out T>. These are two very simple changes that should not have any negative impact on anything else.

      Comment


        #4
        Thank you -- it couldn't be clearer than that. I've logged the suggestion with tracking ID # SFT-868 and linked back to this post to describe the use-case.
        Dave I.NinjaTrader Product Management

        Comment

        Latest Posts

        Collapse

        Topics Statistics Last Post
        Started by tkaboris, Today, 05:13 PM
        0 responses
        2 views
        0 likes
        Last Post tkaboris  
        Started by GussJ, 03-04-2020, 03:11 PM
        16 responses
        3,281 views
        0 likes
        Last Post Leafcutter  
        Started by WHICKED, Today, 12:45 PM
        2 responses
        19 views
        0 likes
        Last Post WHICKED
        by WHICKED
         
        Started by Tim-c, Today, 02:10 PM
        1 response
        10 views
        0 likes
        Last Post NinjaTrader_ChelseaB  
        Started by Taddypole, Today, 02:47 PM
        0 responses
        5 views
        0 likes
        Last Post Taddypole  
        Working...
        X