【问题标题】:Problem with inheritance and List<>继承和 List<> 的问题
【发布时间】:2011-02-19 07:35:32
【问题描述】:

我有一个名为 Grouping 的抽象类。我有一个名为 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 并且 fName 是 GroupingNNA 的属性,而不是 Grouping,因此以下 LINQ 查询对我来说很糟糕。

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

哦,这是编译器错误,而不是运行时错误。在此先感谢您对此提供的任何帮助!

更多信息: 这是不会编译的实际方法。 OfType() 修复了 LINQ 查询,但编译器不喜欢我试图将匿名类型作为 List 返回的事实。

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

【问题讨论】:

    标签: .net linq inheritance list


    【解决方案1】:

    试试:

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

    这将跳过任何不是GroupingNNA 类型的元素,并且还会使编译器使用GroupingNNA 作为g 的类型。

    回应评论和编辑的问题。不,编译器肯定不会对您更改的集合感到满意,但您可以解决这个问题:

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

    这依赖于 .NET 中的数组是协变/反变的,这允许编译器将 GroupingNNA[] 视为构造函数的 Grouping[]

    另外,您不需要if (filtered != null) 检查,您将在filtered 中获得一个集合,它可能不会产生任何元素,但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();
    

    这里的不同方式之间不应该有任何大的性能差异,如果有疑问,请测量它,但我会选择你认为最容易阅读和理解的方式。

    【讨论】:

    • 谢谢!我现在更近了一步。但是,编译器现在并不高兴,因为我试图将匿名类型作为 List 返回。我将使用更多代码对我的原始帖子进行编辑,以便您了解我在说什么。再次感谢。
    【解决方案2】:

    调用 ToList&lt;AnotherType&gt;() 会让自己回到与以前一样的状态 - 不支持通用协变/逆变 - 例如List&lt;Type&gt;List&lt;SubType&gt; 不兼容或不能转换为List&lt;SubType&gt;

    您需要使用filtered.OfType&lt;Grouping&gt;().ToList(); - 第一个让您回到IEnumerable&lt;Grouping&gt; 而不是IEnumerable&lt;GroupingNNA&gt;,然后ToList 只是将IEnumerable 转换为相同泛型类型的List

    【讨论】:

    • .NET 2.x 到 3.5 通用列表是不变的。这是为了你好。期待 .NET 4.0 支持更松散的泛型类型
    猜你喜欢
    • 2010-10-28
    • 2010-10-22
    • 1970-01-01
    • 2021-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多