继承问题和List<>

时间:2010-05-13 22:16:14

标签: .net linq inheritance list

我有一个名为Grouping的抽象类。我有一个名为GroupingNNA的子类。

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

我有一个包含GroupingNNA类型的项目的List,但实际上声明它包含Grouping类型的项目。

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

问题: 以下LINQ查询因为lstGroupings被声明为List&lt;分组&GT;和fName是GroupingNNA的属性,而不是分组。

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

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

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

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 个答案:

答案 0 :(得分:6)

尝试:

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

这将跳过任何非GroupingNNA类型的元素,并使编译器使用GroupingNNA作为g的类型。

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

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

这依赖于.NET中的数组是co / contra-variant的事实,它允许编译器将GroupingNNA[]视为构造函数的Grouping[]

此外,您不需要if (filtered != null)检查,您将在filtered中获得一个集合,它可能不会生成任何元素,但filtered将始终为非{ {1}}。

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

null

甚至只是:

var filtered = from r in lstGroupings.OfType<GroupingNNA>()
               where r.QASensitivity == fSens
               select r;
return new List<Grouping>(filtered.ToArray());
如果删除linq语法,

甚至更短:

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

请注意,您当然也可以使用return new List<Grouping>((lstGroupings.OfType<GroupingNNA>() .Where(r => r.QASensitivity == fSens).ToArray()); 转到其他方式:

OfType

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

答案 1 :(得分:5)

呼叫ToList<AnotherType>()让你自己回到以前的同一条船上 - 不支持通用的协方差/逆变 - 例如List<Type>List<SubType>不兼容或可转换为filtered.OfType<Grouping>().ToList();

您需要使用IEnumerable<Grouping> - 第一个让您回到IEnumerable<GroupingNNA>而不是ToList,然后IEnumerable只需将List转换为一个{{1}}相同的泛型类型。