5

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?

Robin Rodricks
  • 110,798
  • 141
  • 398
  • 607
  • Can you give more detail? What kind of object can have an audio OR video "parent"? What operations do you perform on the parents--would `Object parent` suffice? – John Kugelman Jul 21 '10 at 23:15
  • Yes, as silky has described, you are trying to use inheritance in the wrong way. Audio is not Video and vice versa. However, they are both types of media, and they both consist of some data. That is the interface they should share. – Ed S. Jul 21 '10 at 23:17
  • 2
    "But what if the parents do not inherit from the same baseclass?" The question presupposes a falsehood. Two class types *always* inherit (directly or indirectly) from the same base class: System.Object. – Eric Lippert Jul 21 '10 at 23:26
  • 1
    @Eric: Exactly how is that comment useful? Given it's level of pedanticness, it's also immediately wrong, System.Object doesn't inherit from System.Object. I would think that someone of your stature could actually provide useful feedback. – Noon Silk Jul 21 '10 at 23:41
  • 4
    It is useful feedback because it points out that the poster has forgotten an important point: *the variable could be made to be of type object*. That would certainly solve the problem. – Eric Lippert Jul 22 '10 at 05:01

4 Answers4

8

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# :-)

7

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
  • 54,084
  • 6
  • 88
  • 105
4

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
  • 81
  • 3
1

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
  • 27,329
  • 4
  • 56
  • 102