代码之家  ›  专栏  ›  技术社区  ›  Jagd Dai

继承和列表问题<>

  •  7
  • Jagd Dai  · 技术社区  · 15 年前

    我有一个抽象类叫做分组。我有一个名为groupingnna的子类。

    public class GroupingNNA : Grouping {
      // blah blah blah
    }
    

    我有一个列表,其中包含groupingnna类型的项,但实际上声明为包含grouping类型的项。

    List<Grouping> lstGroupings = new List<Grouping>();
    lstGroupings.Add(
      new GroupingNNA { fName = "Joe" });
    lstGroupings.Add(
      new GroupingNNA { fName = "Jane" });
    

    问题: 由于lstGroupings声明为list<grouping>,而fname是groupingnna的属性,而不是grouping,所以下面的linq查询会在我身上爆炸。

    var results = from g in lstGroupings
                  where r.fName == "Jane"
                  select r;
    

    哦,这是一个编译器错误,不是运行时错误。在此之前,感谢您的帮助!

    更多信息: 下面是无法编译的实际方法。oftype()修复了linq查询,但编译器不喜欢我试图将匿名类型作为列表返回的事实<grouping>。

    private List<Grouping> ApplyFilterSens(List<Grouping> lstGroupings, string fSens) {
    
      // This works now! Thanks @Lasse
      var filtered = from r in lstGroupings.OfType<GroupingNNA>()
                     where r.QASensitivity == fSens
                     select r;
    
      if (filtered != null) {
        **// Compiler doesn't like this now**
        return filtered.ToList<Grouping>();
      }
      else
        return new List<Grouping>();
      }
    
    2 回复  |  直到 15 年前
        1
  •  6
  •   Lasse V. Karlsen    15 年前

    尝试:

    = from g in lstGroupings.OfType<GroupingNNA>()
    

    这将跳过任何不属于类型的元素 GroupingNNA 并使编译器使用 分组导航 作为类型 g .

    回应评论和编辑的问题。不,编译器当然不会满意您更改的集合,但是您可以修复它:

    return new List<Grouping>(filtered.ToArray());
    

    这依赖于.NET中的数组是co/contra变量这一事实,它允许编译器处理 GroupingNNA[] 作为 Grouping[] 对于构造函数。

    另外,你不需要 if (filtered != null) 检查一下,你会得到一个收藏 filtered 可能不会产生任何元素,但是 过滤的 将永远是非- null .

    这意味着您的代码可以写为:

    var filtered = from r in lstGroupings.OfType<GroupingNNA>()
                   where r.QASensitivity == fSens
                   select r;
    return new List<Grouping>(filtered.ToArray());
    

    甚至只是:

    return new List<Grouping>((from r in lstGroupings.OfType<GroupingNNA>()
                               where r.QASensitivity == fSens
                               select r).ToArray());
    

    如果删除LINQ语法,甚至更短:

    return new List<Grouping>((lstGroupings.OfType<GroupingNNA>()
        .Where(r => r.QASensitivity == fSens).ToArray());
    

    请注意,您当然可以使用 OfType 也可以走另一条路:

    return filtered.OfType<Grouping>().ToList();
    

    在这里,不同的方法之间不应该有任何大的性能差异,如果有疑问的话,可以测量它,但是我会用你认为最容易阅读和理解的方法。

        2
  •  5
  •   Chris Ballance    15 年前

    打电话 ToList<AnotherType>() 把自己放回原来的船上-不支持一般协方差/反方差-例如。 List<Type> 不兼容或可转换为 List<SubType> .

    你需要使用 filtered.OfType<Grouping>().ToList(); -第一个让你回到 IEnumerable<Grouping> 而不是 IEnumerable<GroupingNNA> 然后 ToList 只是转换 IEnumerable 到A List 属于相同的泛型类型。