在LINQ中优化IEnumerable到HashSet转换

时间:2012-06-28 13:58:03

标签: performance linq ienumerable hashset

public HashSet<Student> GetStudents(int studentId)
{
    IEnumerable<Student> studentTypes = this.studentTypes .Where(x => (x.studentID== studentId));
    if (studentTypes .FirstOrDefault() != null)
    {

        //return new HashSet<Student>(studentTypes);
        return studentTypes.ToHashSet();
    }
    else
    {
        return new HashSet<Student>();
    }
}

public static class LinqUtilities
{
    public static HashSet<T> ToHashSet<T>(this IEnumerable<T> enumerable)
    {
        HashSet<T> hashSet = new HashSet<T>();

        foreach (var en in enumerable)
        {
            hashSet.Add(en);
        }

        return hashSet;
    }
}

这个函数被称为很多次,比如1000次,结果集中有5000个学生。 如何优化此功能...我知道从IEnumerableHashSet的转换会导致很多开销。 ToHashSet是我的扩展方法。 这个功能是减慢和吃很多时间。

2 个答案:

答案 0 :(得分:10)

首先,您不需要枚举实用程序函数中的哈希值 你可以通过使用@Jon

编写的漂亮的静态扩展类来提高效率

Converting linq result to hashset

我认为您不需要检查FirstOrDefault,因为扩展将处理给定T的新学生对象 所以你可以换成干净整洁的方式。

IEnumerable<Student> studentTypes = this.studentTypes.Where(x => (x.studentID== studentId));
return studentTypes.toHashSet();

另一个选项是你可以将IEnumerable传递给你的HashSet构造函数 喜欢

HashSet<Student> studentTypes = new HashSet<Student>(this.studentTypes.Where(x => (x.studentID== studentId)));

所以你的GetStudents函数中只有一行代码

答案 1 :(得分:4)

每次调用都不要运行两次查询。

 //sets up a deferred query.  This query will be "executed" when enumerated.
IEnumerable<Student> studentTypes = this.studentTypes
  .Where(x => (x.studentID== studentId));

 //enumeration #1 (stops on first hit)
if (studentTypes .FirstOrDefault() != null)
{
   //enumeration #2
   return studentTypes.ToHashSet(); 

您的病情是不必要的:

 //sets up a deferred query.  This query will be "executed" when enumerated.
IEnumerable<Student> studentTypes = this.studentTypes
  .Where(x => (x.studentID== studentId));

 //enumeration #1
 return studentTypes.ToHashSet(); 

  

我知道从Ienumerable到Hasset的转换导致了很多   间接费用

那是公牛。你没有测量任何东西,误导自己优化错误的代码部分。