实现自己的LINQ&amp;的IEnumerable <T> </T>

时间:2009-08-04 21:38:31

标签: c# .net linq performance ienumerable

在我正在开发的项目中,实际上有大量的集合(1M-1B元素),并且事物主要被修改为集合。

这是一款实时应用,因此性能至关重要。

对于某些操作,如Reverse,BinarySearch(可能的?)等会比Select等等遭受更多的打击。

使用可能的MoveNext,MovePrev等实现自己的IEnumerable是否可行,并且自己实现了利用这些扩展的LINQ扩展?

如果发生这种情况,它将在项目结束时发生。因为我们需要先让它工作,然后加快速度。

总而言之,这不应该是太多的工作,对吗?

4 个答案:

答案 0 :(得分:9)

非常有可能创建自己的Enumerable实现,这可能是特殊情况下的某些情况。您基本上想要检测自己的集合类型(或者可能只是集合,例如List<T>),并在适用的情况下使用更有效的实现。

我有一个sample project,我曾用它来演示“在一小时内实现LINQ to Objects”,您可能需要查看这些示例。它不是一个完整的实现,特别是它比实际的LINQ to Objects 更少效率 - 但你仍然可能觉得它很有趣。

或者,您可能会发现i4o (Indexed LINQ)完成了您需要的所有内容 - 或者您最好不要从头开始做出贡献。值得一试。

请记住,在一天结束时,LINQ基本上是一个很好的设计加上语法糖。例如,C#编译器不知道关于System.Linq.Enumerable任何特殊内容。

答案 1 :(得分:2)

如果你真的想要表现,你可以做很多事情。请记住以下选择:

var result = from element in collection
             where element.Id == id
             select element;

编译为:

var result = collection.Where(element => element.Id == id);

如果为collection类型创建以下方法,则可以利用主要操作与Id成员相等的事实,并以优化的方式处理请求。重要的是正确识别集合中的性能关键操作,并选择正确的算法(即复杂性)来执行它们。

public IEnumerable<TElement> Where(Expression<Func<TElement, bool>> selector)
{
    // detect equality of the Id member and return some special value
}

答案 2 :(得分:2)

考虑System.Linq.Enumerable.Reverse() - 此方法在返回第一个结果之前完全枚举IEnumerable。

如果您的查询是myCollection.Reverse()。Take(10),并且您的集合中有数十亿项,那么枚举数十亿项以获得10项是一个可怕的想法。

如果你在自己的类型上提供了一个Reverse方法,你可以提供一个更好的实现,它只是在集合上向后循环(可能是索引)。

关键是提供您自己的类型来控制实现。您不能使用适用于所有IEnumerable<T>的实现,因为这些实现不会充分利用您的自定义集合类型的功能。

答案 3 :(得分:1)

  

实施自己的可行性是否可行   IEnumerable与可能的MoveNext,   MovePrev等自己实现了LINQ   利用的扩展   这些?

IEnumerable(或更恰当地,IEnumerator)没有MovePrev。您可以定义一个界面:

public interface IReversable<T> : IEnumerable<T>
{
    IEnumerator<T> GetReverseEnumerator();
}

这可以由支持有效反向枚举的任何容器实现。

然后你可以写一个Reverse的重载(扩展方法)来处理这个新接口,以及实现接口的集合类等等。然后你必须使用那些集合类而不是标准的,如List<T>

但是(我没有方便检查反射器)可能内置的Reverse足够智能,如果可以从IList接口获得{{1}}接口,则可以快速做事。收集,无论如何都会优化最常见的情况。

因此,这种方法可能没有太多意义。