Увеличена сложность LINQ OrderBy.First{OrDefault}
Реализация OrderBy.
First<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) и OrderBy.
FirstOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) изменилась, что привело к увеличению сложности операции.
Описание изменения
В .NET Core версий 1.x–3.x вызов OrderBy или OrderByDescending, за которым следовал вызов First<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) или FirstOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>), выполнялся с уровнем сложности O(N)
. Так как требуется только первый элемент (элемент по умолчанию), для его поиска требуется только одно перечисление. Однако предикат, передаваемый в First<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) или FirstOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>), вызывается ровно N
раз, где N
— длина последовательности.
В .NET 5 и более поздних версиях было внесено изменение, вследствие которого вызов OrderBy или OrderByDescending, за которым следует First<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) или FirstOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>), выполняется с уровнем сложности O(N log N)
, а не O(N)
. Однако предикат, который передается в First<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>) или FirstOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>), может вызываться менее чем N
раз, что более важно для общей производительности.
Примечание.
Это изменение соответствует реализации и сложности операции в .NET Framework.
Причина изменения
Преимущество вызова предиката меньшее число раз перевешивает общее снижение сложности, поэтому реализация, появившаяся в .NET Core 1.0, была отменена. Дополнительные сведения в описании этой проблемы dotnet/runtime.
Представленные версии
5,0
Рекомендуемое действие
От разработчика не требуется никаких действий.