views:

109

answers:

4

I frequently link objects to their parents using:

 Video parent;

Sometimes I have objects that can be children of different object types, so do I:

 int parentType;
 Video parentVideo; // if parent == VIDEO then this will be used
 Audio parentAudio; // if parent == AUDIO then this will be used

Is there a better way? How do I work with a variable that can be an instance of different types?

Edit: Of course, if Video and Audio inherit from the same baseclass (eg. Media) I could do this:

 Media parent;

But what if the parents do not inherit from the same baseclass?

+7  A: 

Well, generally an interface which exposes all functionality is appropriate, and this can be your type. Otherwise (or as well as) you may consider generics:

Like so:

class Something<TMediaType>
    where TMediaType : IMedia // use this statement to limit the types. It
                              // is not required, if not specified it can be 
                              // of any type
{
    TMediaType data;

    // other such things
}
Noon Silk
+7  A: 

I am assuming that the types in your question are sealed. In which case I would just use object parent and use as on the way out. (Using as can have a higher performance impact than checking a flag, but... not a concern in anything I have done and it can also be nicely used in a null-guard.)

Video video = null;
if ((video = parent as Video) != null) {
  // know we have a (non-null) Video object here, yay!
} else if (...) {
  // maybe there is the Audio here
}

The above is actually just a silly C# way of writing a one-off-pattern-match on an unconstrained discriminated union (object is the union of every other type in C# :-)

pst
+1 Interesting way of thinking about it...
Chuck Conway
+1  A: 

If there is not a base class Media from which they derive, but there is common functionality that could apply equally well to Audio or Video content, then you could create a new MediaContainer class that accepts an Object Content and performs operations differently depending on the specific type of Content. What this does is encapsulate the ugly 'switching' functionality into a wrapper so that you can write code that depends on a MediaContainer without worrying about the specific Media it contains or how it handles the ugly work of delegating the calls.

Dan Bryant
+2  A: 

Try turning things around....does this make more sense ?

interface IMedia 
{
  void Play();
  void Stop();
}

class Video : IMedia
{
  public Audio Audio; /// aka child

  public void Play() { }
  public void Stop() { }
}

class Audio : IMedia
{
  public Video Video; /// aka parent...questionable unless Audio 
                      /// always has a parent Video

  public void Play() { }
  public void Stop() { }
}

private void PlayAnyMedia(IMedia media) /// Write against an interface
{
  media.Play();
}
CRMay