Отображение объектов с помощью цикла foreach - PullRequest
2 голосов
/ 03 ноября 2011

У меня проблема при получении данных из ArrayList и отображении их в текстовые поля.Я получаю ошибку: Unable to cast object of type 'Lab_9.Book' to type 'Lab_9.Magazine'.Я попытался использовать 2 цикла foreach, но об этом, похоже, не может быть и речи.Как я мог избежать этой проблемы?

Проблема возникает здесь:

    // Displaying all Book objects from pubs ArrayList.
    foreach (Book list in pubs)
    {
        bookNumber++; // Count books from the begining.

        // Displaying and formating the output 
        // in txtBookList textbox.
        bookList.txtBookList.Text +=
            "=== Book " + bookNumber + " ===" + Environment.NewLine +
            list.Title + Environment.NewLine +
            list.getAuthorName() + Environment.NewLine +
            list.PublisherName + Environment.NewLine +
            "$" + list.Price + Environment.NewLine
            + Environment.NewLine;
    }

С уважением.

Ответы [ 3 ]

3 голосов
/ 03 ноября 2011

это позволит вам иметь только один цикл, но это не очень

foreach (object publication in pubs)
{
   var book = publication as Book;
   var magazine = publication as Magazine;
   if (book != null) {
     //it's a book, do your thing
   } else if (magazine != null) {
     //it's a magazine, do your thing
   } else {
    throw new InvalidOperationException(publication.GetType().Name + " is not a book or magazine: ");
   }
}

Вместо наследования вы действительно хотите определить интерфейс, который включает в себя общие свойства и методы всех публикаций.

public interface IPublication
{
  string Title {get;set;}
  float Price {get;set;}
  // etc.
}

Затем ваши классы реализуют интерфейс

public class Book : IPublication
{
  public string Title {get;set;}
  public float Price {get;set;}
  //the rest of the book implementation
}

public class Magazine: IPublication

{
  public string Title {get;set;}
  public float Price {get;set;}
  //the rest of the magazine implementation
}

. Теперь у вас намного больше гибкости, но для ваших целей вы можете оставить оставшуюся часть кода без изменений.и используйте только один цикл, который намного чище и более встроен в решение jwJung

foreach (var publication in pubs.OfType<IPublication>())
{
  // publication is either a book or magazine, we don't care we are just interested in the common properties
  Console.WriteLine("{0} costs {1}",  publication.Title, publication.Price);
}
2 голосов
/ 03 ноября 2011

Элементы вашего объекта паба (ArrayList) являются экземплярами типа Object для книг и журналов.Поэтому вам нужно отфильтровать, используя .OfType () для отображения каждого типа.Этот метод возвращает только экземпляры целевого типа (T) в ArrayList.

foreach (Book list in pubs.OfType<Book>())
{
}

foreach (Magazine list in pubs.OfType<Magazine>())
{
}

Чтобы объединить два foreach, я предлагаю вам переопределить ToString () или создать базовый класс, имеющий строкуимущество.Для использования базового класса установите все значения (например, title + "," + bookNumber ...) в строковое свойство.Я покажу вам переопределение ToString ().

internal class Book
{
    public override string ToString()
    {
        return "=== Book " + bookNumber + " ===" + Environment.NewLine +....;
    }
}

internal class Magazine
{
    public override string ToString()
    {
        return "=== Publication: " + bookNumber + ....;
    }
}

И затем вы можете объединить два цикла.

foreach (string item in pub)
{
    Console.WriteLine(item.ToString());
}
1 голос
/ 03 ноября 2011

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

foreach (var list in pubs)
{
    if(list is Book)
    {
        Book tmp = (Book)list;
        // Print tmp.<values> 
    }

    if(list is Magazine)
    { 
        Magazine tmp = (Magazine)list;
        // Print tmp.<values>         
    }
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...