У меня есть базовый класс с именем 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
, почему он бросает исключение? Есть ли лучший способ обойти это?
Ваша ошибка в другом месте. То, что вы написали, прекрасно, если оба видео и фото наследуются от Media. Возможно, вы пытаетесь сделать это неправильно где-то еще.
Попробуйте это...
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 и вызовет проблемы позже. Второй, я не возвращаю то, что я возвращаю. Все кастинг подразумевается или обрабатывается компилятором, поэтому мне не нужно это делать. Третий, он компилируется и работает, как и ваш исходный код. Ваша проблема происходит где-то в другом месте, так как вы обнаружите, что вы отбросили этот код в консольное приложение и протестировали его.
Не следует ли вводить метод с возвратом доходности IEnumerable<Media>
, а не IEnumerator<Media>
?
Но в большей степени этот шаблон оставляет мне плохой запах. Каждый раз, когда вы используете foreach в этой "коллекции", вы будете создавать (создавать экземпляры) новые экземпляры каждого объекта Photo
или Video
в списке _mediaElement.Elements()
. Это действительно то, что вы хотите?
Похоже, вы пытаетесь добавить экземпляры Media
в коллекцию Video
, и он взрывается, потому что один или несколько из них - это Photo
- вы пытаетесь добавить фотографию в видео коллекция. Ошибка в коде клиента, а не в сгенерированном перечислителе.