18

我有两节课。第一个是Person,第二个是Student(继承自 Person)。我想过滤一个通用列表并找到所有学生的成绩高于 7。我想出了以下解决方案:

class Person
{
    public string Name {get; set;}
}

class Student : Person
{
    public decimal Grade {get; set;}
}

class Program
{
    static void Main(string[] args)
    {
        List<Person> people = new List<Person>();
        people.Add(new Person() {Name="John"});
        people.Add(new Student() {Name="Joe", Grade=6});
        people.Add(new Student() {Name="Jane", Grade=8});

        people.Where(delegate (Person person) {
            var student = person as Student;
            return student != null && student.Grade > 7;
        });
    }
}

有没有更简单的方法来过滤这个列表?

4

3 回答 3

33

我看到的唯一改进是使用OfType,像这样

var result = people.OfType<Student>().Where(s => s.Grade > 7);

...而且我的语法更简单...但这是旁观者的看法。

于 2013-06-22T22:35:15.157 回答
4

这里有几种不同的方法,以及一些相对的性能数据:

最初的

people.Where(delegate(Person person)
{
    var student = person as Student;
    return student != null && student.Grade > 7m;
});

初始修改 (与初始速度相同)

people.Where(p =>
{
    var student = p as Student;
    return student != null && student.Grade > 7m;
});

OfType (比初始速度慢 40-52%)

people.OfType<Student>().Where(s => s.Grade > 7m)

Foreach (比 Initial 快 9-16%)

var results = new List<Student>();
foreach (var person in people)
{
    var student = person as Student;
    if (student != null && student.Grade > 7m)
    {
         results.Add(student);
    }
}

对于 (比初始速度快 12-18%)

var results = new List<Student>();
for (var idxPerson = 0; idxPerson < people.Count; idxPerson++)
{
    var student = people[idxPerson] as Student;
    if (student != null && student.Grade > 7m)
    {
        results.Add(student);
    }
}

为了获得性能数据,我:

  • 进行了无任何作用的对照测试
  • 在具有 10 到 1,000,000 个元素的列表上为每个函数计时 100 次
  • 从每个测试时间中减去控制时间(使结果更准确)
  • 每个函数使用相同的随机数据集,并使用 ToList 强制枚举器运行

当然,这些只是我机器上的性能数据,你必须在真实世界的数据上进行测试才能得到实际结果,因为学生与人的分布、学生的平均成绩等会导致很多时间的变化。

于 2014-06-04T15:09:51.440 回答
1
people.RemoveAll(p => p.Grade <= 7);
于 2016-11-10T09:18:39.443 回答