【问题标题】:C# foreach on children of an abstractC# foreach 抽象的子级
【发布时间】:2016-08-12 07:16:19
【问题描述】:

我是 C# 新手,我的问题是:
我有一个名为

的类

抽象项目

这个班有 3 个孩子。 我的代码是:

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()
                        });
                }
            }
        }
    }

我要做的是获取此列表中与 getByChosenField 匹配的所有值。
现在,在我的例子中,GetByChosenField 是一个 BookName,它返回列表中当前具有 BookName 名称的所有书籍。
进行搜索的代码确实有效。
问题是,如果我在 Cooking 以及 Reading 和\或 Science 中有书名 Harry Potter,我收到一个错误:

附加信息:无法将“CommonBookLib.Cooking”类型的对象转换为“CommonBookLib.Reading”类型。

仅当我至少有 2 个其他类别(阅读\烹饪\科学\期刊)的书名时才会出现此错误。
如果是一本书的名字,一切都很好。
我在这里错过了什么?

【问题讨论】:

  • 抽象父级没有定义一个所有子级都可以继承的简单SubCategory 成员是否有原因。这将使代码更简单,您只需要一个 foreach 而不是 3 并且只需将 foreach 设置为 foreach(AbstractItem item in getByChosenField)
  • 另外,如果列表很大,执行 4 foreach 可能会很慢。你可能要考虑做一个foreach(var abstractItem in getByChosenField) 然后在foreach 里面做var scienceItem = abstractItem as Science;
  • @ScottChamberlain 你所说的现在实际上效果更好。在我可能突然获得另一个类别之前,现在使用 var bla = item 作为类型,它的效果非常好。究竟是什么?目的是什么?有什么资料可以理解吗?
  • 从 MSDN How to: Safely Cast by Using as and is Operators 看到,你可能想做“UseAsOperator` 函数示例。基本上as 会检查右边的类型是否可以被强制转换,如果可以的话它返回强制转换类型,如果不能返回null

标签: c# list foreach abstract children


【解决方案1】:

你快到了。

您知道如何将列表过滤到特定子类型的那些项目。

只需将该过滤器应用于您正在迭代的IEnumerable

        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()
                    });
            }
        }

当然,一旦我们这样做了,if 子句就变得多余了。如果没有匹配类型的项目,它将简单地跳过循环。

 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
 }

【讨论】:

  • 出于某种原因我仍然得到这个:Additional information: Unable to cast object of type 'CommonBookLib.Cooking' to type 'CommonBookLib.Reading'.。我不明白..如果我确保过滤它并且它适用于一个值而不是为什么多个值会出现异常?似乎对于一个值,会发生其中一个 foreach 条件,但对于两个或更多它会发生冲突。
  • 该死!刚才我看到了你提出的第二个条件。谢谢,这就是答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-04-03
  • 2018-11-01
  • 1970-01-01
  • 2012-02-05
  • 2022-08-18
  • 2011-09-01
  • 1970-01-01
相关资源
最近更新 更多