Как вы работаете с переменной, которая может быть нескольких типов? - PullRequest
4 голосов
/ 22 июля 2010

Я часто связываю объекты с их родителями, используя:

 Video parent;

Иногда у меня есть объекты, которые могут быть дочерними объектами разных типов, поэтому я:

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

Есть ли лучший способ? Как мне работать с переменной, которая может быть экземпляром разных типов?

Редактировать: Конечно, если видео и аудио наследуют от одного базового класса (например, медиа), я мог бы сделать это:

 Media parent;

Но что, если родители не наследуют от одного и того же базового класса?

Ответы [ 4 ]

9 голосов
/ 22 июля 2010

Я предполагаю, что типы в вашем вопросе запечатаны.В этом случае я бы просто использовал object parent и использовал as на выходе.(Использование as может оказать более сильное влияние на производительность, чем проверка флага, но ... это не имеет значения для всего, что я сделал, и его также можно использовать с нулевой защитой.)

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
}

Вышесказанное на самом деле является просто глупым способом написания на C # одноразового сопоставления с неограниченным распознаваемым объединением (объект - это объединение любого другого типа в C #: -)

7 голосов
/ 22 июля 2010

Ну, как правило, интерфейс, который предоставляет все функциональные возможности, подходит, и это может быть вашим типом. В противном случае (или также) вы можете рассмотреть дженерики:

Вроде так:

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
}
3 голосов
/ 22 июля 2010

Попробуйте перевернуть вещи ... это имеет больше смысла?

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();
}
1 голос
/ 22 июля 2010

Если нет базового класса Media, из которого они получены, но есть общие функциональные возможности, которые могут одинаково хорошо применяться к аудио или видео контенту, тогда вы можете создать новый класс MediaContainer, который принимает объектный контент и выполняет операции по-разному в зависимости отна конкретный тип контента.Что это делает, так это инкапсулирует уродливую функциональность «переключения» в оболочку, так что вы можете писать код, который зависит от MediaContainer, не беспокоясь о конкретных носителях, которые он содержит, или о том, как он обрабатывает уродливую работу по делегированию вызовов.

...