Использование yield return для возврата объектов, которые наследуют форму базового типа

2

У меня есть базовый класс с именем Media с двумя классами, которые наследуют его, Photo и Video. Я пытаюсь создать коллекцию для базового класса мультимедиа для хранения этих фото и видео объектов. Поэтому я создал класс MediaList следующим образом:

public class MediaList: ICollection<Media>
{
    private readonly XElement _mediaElement;

    public MediaList(XElement mediaElement)
    {
        _mediaElement = mediaElement;            
    }

    public IEnumerator<Media> GetEnumerator()
    {
        foreach (XElement element in _mediaElement.Elements())
        {
            Media media;
            switch (element.Name.LocalName)
            {
                case "video":
                    media = new Video(element);
                    break;
                case "photo":
                    media = new Photo(element);
                    break;
                default:
                    media = null;
                    break;
            }
            yield return media;
        }
    }

    //Rest of ICollection Implementation
}

Когда я повторяю список, я получаю следующее исключение:

Значение "Tool.Photo" не относится к типу "Tool.Video" и не может использоваться в этой общей коллекции.

Если я возвращаю объект Media, почему он бросает исключение? Есть ли лучший способ обойти это?

  • 0
    Медиа абстрактный?
  • 0
    Нет медиа не абстрактно
Показать ещё 3 комментария
Теги:
generics
collections

4 ответа

2
Лучший ответ

Ваша ошибка в другом месте. То, что вы написали, прекрасно, если оба видео и фото наследуются от Media. Возможно, вы пытаетесь сделать это неправильно где-то еще.

  • 0
    Покопавшись, вы правы, моя проблема в другом месте. Вопросы где? Вздохните, чтобы пройтись по коду :-)
3

Попробуйте это...

class Program
{
    static void Main(string[] args)
    {
        var array = new string[] { "video", "photo", "hurf", "photo" };
        var ml = new MediaList(array);
        foreach(var element in ml)
            Console.WriteLine(element.GetType().Name);
        Console.Read();
    }
}

public class Media { }
public class Video : Media { }
public class Photo : Media { }

public class MediaList
{
    private string[] elements;
    public MediaList(string[] elements) { this.elements = elements; }
    public IEnumerator<Media> GetEnumerator()
    {
        foreach (string s in elements)
            switch (s)
            {
                case "video":
                    yield return new Video();
                    break;
                case "photo":
                    yield return new Photo();
                    break;
            }
    }
}

Вы можете щелкнуть это в консольном приложении, чтобы проверить его.

Обратите внимание на пару разных вещей. Сначала, вы никогда не дадите return null. Это не имеет ничего общего с вашей проблемой, но никто не ожидает, что перечислит значение null и вызовет проблемы позже. Второй, я не возвращаю то, что я возвращаю. Все кастинг подразумевается или обрабатывается компилятором, поэтому мне не нужно это делать. Третий, он компилируется и работает, как и ваш исходный код. Ваша проблема происходит где-то в другом месте, так как вы обнаружите, что вы отбросили этот код в консольное приложение и протестировали его.

  • 0
    +1 Это точный код, который у меня был в начале, пока я не спустился не с того кролика целиком :-)
1

Не следует ли вводить метод с возвратом доходности IEnumerable<Media>, а не IEnumerator<Media>?

Но в большей степени этот шаблон оставляет мне плохой запах. Каждый раз, когда вы используете foreach в этой "коллекции", вы будете создавать (создавать экземпляры) новые экземпляры каждого объекта Photo или Video в списке _mediaElement.Elements(). Это действительно то, что вы хотите?

  • 0
    нет то, что он имеет, это хорошо.
  • 0
    Разве доходность не возвращает объекты Media? (не перечислитель медиа-объектов.)
Показать ещё 3 комментария
0

Похоже, вы пытаетесь добавить экземпляры Media в коллекцию Video, и он взрывается, потому что один или несколько из них - это Photo - вы пытаетесь добавить фотографию в видео коллекция. Ошибка в коде клиента, а не в сгенерированном перечислителе.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню