禁用LINQ优化以实现自定义IList实现

时间:2018-11-02 13:45:34

标签: .net linq

如果提供的集合实现了Select接口,则

LINQ的方法WhereSelectManyIList<T>(也许不确定,其他方法)使用优化的实现-它不使用{{1 }}方法,但改为通过索引检索元素(我想至少是在dotnet核心中,以避免使用枚举器开销)。

是否可以针对某些类型禁用该优化?

我有GetEnumerator实现,该实现代理对另一个集合的所有调用,因此,使用枚举器迭代所有元素实际上比按索引获取所有元素快得多。

3 个答案:

答案 0 :(得分:0)

以下是Linq方法,它们查看集合实际上是IList还是ICollection并使用索引访问而不是枚举器:

  • First / FirstOrDefault / Single / SingleOrDefault(如果未传递谓词,则使用list[0]
  • Last / LastOrDefault(如果未传递谓词,则使用list[count-1]
  • ElementAt / ElementAtOrDefault
  • Count(如果不使用谓词,则调用ICollection.Count()
  • Contains(呼叫ICollection.Contains

SelectWhereOrderBy,所有其他人都将使用枚举器。

一些选项是:

  • 如果索引访问器的速度比枚举器慢,请在查询中加入Select(x => x),从而用枚举器包装集合
  • 修复索引访问器,使它们至少在这些特定情况下表现出色
  • 低效率地生活。

答案 1 :(得分:0)

当然可以。专门为您的类型实现给定的方法。您可以提供特定于类型的实现,既可以作为扩展方法也可以作为实例方法,编译器会选择它们,因为它们更加具体(自然地,扩展方法必须在范围内才能被考虑)。

可以找到针对System.Collections.Immutable.ImmutableArray<T>的类型特定的LINQ方法优化的示例。

答案 2 :(得分:0)

我的建议是创建一个IEnumerable扩展函数,该函数接受一个输入序列,并返回与IEnumerable相同的序列。

请参见Extension Methods Demystified

public static IEnumerable<TSource> ToEnumerable (this IEnumerable<TSource> source)
{
     foreach (var sourceItem in source)
         yield return sourceItem
}

用法:

List<Person> persons = ...

var personList = persons.ToList(); // uses the fact that Persons implements IList

var otherList = persons.ToEnumerable().ToList();
// does not implement IList<...>, and thus doesn't use the optimization