【问题标题】:Enumeration of a list of a class which has inheritence of 2 classes枚举具有 2 个类继承的类的列表
【发布时间】:2015-05-08 12:41:09
【问题描述】:

我使用以下代码在我的代码中创建了一个可枚举的类:

public class ItemCollection : IEnumerable<AbstractItem>
{
    private List<AbstractItem> Items;

    public IEnumerator<AbstractItem> GetEnumerator()
    {
        return Items.GetEnumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

效果很好,但是我遇到了一个问题: AbstractItem 有两个继承类,Book 和 Journal,它们都从 AbstractItem 继承对象并有一些自己的(它们都从 AbstractItem 获得“Name”,但只有 Book 有“BGenre”,只有 Journal 有“JTopic”),因为我实现了AbstractItem 的 iEnumerator,我不能使用继承类在 foreach 循环中的对象。我该如何解决?

【问题讨论】:

  • 你能提供你想要的代码在foreach循环中使用继承类的对象吗?
  • 你可以让你的集合通用: public class ItemCollection : IEnumerable where T : AbstractItem

标签: c# inheritance ienumerable ienumerator


【解决方案1】:

您可以使用 Linq 过滤掉Books、Journals 等等:

ItemCollection collection = ...

var books = collection
  .OfType<Book>();

var journals = collection
  .OfType<Journal>();

例如,打印出所有BGenres:

  String bGenres = String.Join(Environment.NewLine, collection
    .OfType<Book>()
    .Select(book => book.BGenre.ToString()));

  Console.Write(bGenres); 

【讨论】:

    【解决方案2】:
    foreach (AbstractItem item in collection)
    {
        // common book and journal code here
        if (item is Book)
        {
            // some code for books
        }
        else if (item is Journal)
        {
            // some code for journals
        }
    }
    
    // another way:
    List<Book> books = collection.OfType<Book>().ToList();
    List<Journal> journals = collection.OfType<Journal>().ToList();
    

    【讨论】:

      【解决方案3】:

      你可以使用泛型:

      public class ItemCollection<T> : IEnumerable<T>
      {
          private List<T> Items;
      
      public IEnumerator<T> GetEnumerator()
      {
          return Items.GetEnumerator();
      }
      
      System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
      {
          return GetEnumerator();
      }
      }
      

      然后你可以这样做:

      var books = new ItemCollection<Book>();
      foreach(var book in books)
      {
      doSomething(book.BookProperty);
      }
      

      var journals = new ItemCollection<Journal>();
      foreach(var journal in journals)
      {
      doSomething(journal.JournalProperty);
      }
      

      或在访问摘要时

      var items = new ItemCollection<AbstractItem>();
      foreach(var item in items)
      {
      doSomething(item.AbstractItemProperty);
      }
      

      【讨论】:

      • 你不能这样做 var books = new ItemCollection&lt;Book&gt;(); 因为 public class ItemCollection : IEnumerable&lt;T&gt; 不遵守
      • 你需要在类ItemCollection&lt;T&gt;上定义泛型变量
      • 是的,我的错,错字,已修复。
      【解决方案4】:

      我不知道你是否在实现你的抽象类方面做得很好。但在这种情况下,您可以使用反射来访问类的属性。像这样:

      foreach (AsbtractClass Item in ItemCollection)
              {
                  System.Reflection.PropertyInfo BGenre = Item.GetType().GetProperty("BGenre");
                  System.Reflection.PropertyInfo JTopic = Item.GetType().GetProperty("JTopic");
      
                  if (BGenre != null) TxtResultBGenre.Text = BGenre.GetValue(Item).ToString();
                  if (JTopic != null) TxtResultJTopic.Text = BGenre.GetValue(Item).ToString();
              }
      

      或者你可以分析Item的数据类型,得到已知的属性。

       foreach (AsbtractClass Item in ItemCollection)
                  {
                      if (Item is Book)
                          TxtResultBGenre.Text = System.Reflection.PropertyInfo BGenre = Item.GetType().GetProperty("BGenre").GetValue(Item).ToString();
                      else if (Item is Journal)
                          TxtResultJTopic.Text = System.Reflection.PropertyInfo JTopic = Item.GetType().GetProperty("JTopic").GetValue(Item).ToString();
                  }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-11-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-16
        相关资源
        最近更新 更多