Search code examples
c#listforeachabstractchildren

C# foreach on children of an abstract


I'm new to C# and my question is:
I have a class named

AbstractItem

and there are 3 children to this class. My code is:

private void AddChecker(List<AbstractItem> getByChosenField)
    {
        if (getByChosenField == null)
        {
            MessageBox.Show("Entry list is currently empty.");
        }
        else {
            LibraryList.Items.Clear(); // simply if there are no results then list remains empty.
            if (getByChosenField.OfType<Reading>().Count() > 0)
            {
                foreach (Reading item in getByChosenField)
                {
                    LibraryList.Items.Add(
                        new MyItems
                        {
                            ItemName = item.ItemName,
                            CopyNumber = int.Parse(item.CopyNumber.ToString()),
                            Guid = int.Parse(item.Guid.ToString()),
                            TimePrinted = item.Time,
                            BestSeller = item.BestSeller,
                            Category = item.BookCategory.ToString(),
                            SubCategory = item.ReadingBookSubCategory.ToString()
                        });
                }
            }
            if (getByChosenField.OfType<Cooking>().Count() > 0)
            {
                foreach (Cooking item in getByChosenField)
                {
                    LibraryList.Items.Add(
                        new MyItems
                        {
                            ItemName = item.ItemName,
                            CopyNumber = int.Parse(item.CopyNumber.ToString()),
                            Guid = int.Parse(item.Guid.ToString()),
                            TimePrinted = item.Time,
                            BestSeller = item.BestSeller,
                            Category = item.BookCategory.ToString(),
                            SubCategory = item.CookingBookSubCategory.ToString()
                        });
                }
            }
            if (getByChosenField.OfType<Science>().Count() > 0)
            {
                foreach (Science item in getByChosenField)
                {
                    LibraryList.Items.Add(
                        new MyItems
                        {
                            ItemName = item.ItemName,
                            CopyNumber = int.Parse(item.CopyNumber.ToString()),
                            Guid = int.Parse(item.Guid.ToString()),
                            TimePrinted = item.Time,
                            BestSeller = item.BestSeller,
                            Category = item.BookCategory.ToString(),
                            SubCategory = item.ScienceBookSubCategory.ToString()
                        });
                }
            }
            if (getByChosenField.OfType<Journal>().Count() > 0)
            {
                foreach (Journal item in getByChosenField)
                {
                    LibraryList.Items.Add(
                        new MyItems
                        {
                            ItemName = item.ItemName,
                            CopyNumber = int.Parse(item.CopyNumber.ToString()),
                            Guid = int.Parse(item.Guid.ToString()),
                            TimePrinted = item.Time,
                            Category = "Journal",
                            SubCategory = item.JournalCategory.ToString()
                        });
                }
            }
        }
    }

What I'm trying to do is getting all of the values inside this List that matches getByChosenField.
Now, GetByChosenField in my case is a BookName that returns all of the books in the list that are currently with the BookName name.
The code that does the searching is indeed working.
The problem is, if I have a book name Harry Potter inside Cooking and also Reading and\or Science, I get an error:

Additional information: Unable to cast object of type 'CommonBookLib.Cooking' to type 'CommonBookLib.Reading'.

This error occures only when I have at least 2 book names of other Categories (Reading\Cooking\Science\Journal).
In case of one book name, everything is fine.
What am I missing here?


Solution

  • You're nearly there.

    You know how to filter the list to those items of a specific subtype.

    Just apply that filter to the IEnumerable you are iterating over

            if (getByChosenField.OfType<Reading>().Any()) // Faster than Count() > 0
            {
                foreach (Reading item in getByChosenField.OfType<Reading>())
                {
                    LibraryList.Items.Add(
                        new MyItems
                        {
                            ItemName = item.ItemName,
                            CopyNumber = int.Parse(item.CopyNumber.ToString()),
                            Guid = int.Parse(item.Guid.ToString()),
                            TimePrinted = item.Time,
                            BestSeller = item.BestSeller,
                            Category = item.BookCategory.ToString(),
                            SubCategory = item.ReadingBookSubCategory.ToString()
                        });
                }
            }
    

    Of course, once we do this, the if clause becomes superfluous. If there are no items of the matching type, it will simply skip over the loop.

     foreach (Reading item in getByChosenField.OfType<Reading>())
     {
          // Add the Reading item
     }
     foreach(Cooking item in getByChosenField.OfType<Cooking>()) 
     {
        //Add the Cooking item
     }
     foreach(Science item in getByChosenField.OfType<Science>())
     {
        // Add the science item
     }