λ1202: Prefer the Enumerable form of the Sequence constructor

Since 3.8.0 the constructors of Funcky.Sequence also exist as static extension members of System.Linq.Enumerable, next to Enumerable.Range and Enumerable.Repeat: Sequence.Successors(1, n => n + 1) is Enumerable.Successors(1, n => n + 1).

Cause

A constructor of Sequence (Return, FromNullable, Successors, Cycle, CycleRange, CycleMaterialized, RepeatRange, RepeatMaterialized, Concat) is called, the file is compiled as C# 14 or later, and the same call with Enumerable as the receiver binds to the Enumerable block of EnumerableExtensions. A call that would bind to an overload of Enumerable itself is left alone, and so is one inside an expression tree.

A method group (values.Select(Sequence.Return)) is not reported: a static extension member has no method-group form of the same shape.

Reason for rule

The constructors sit where the base class library keeps its own sequence constructors, so a reader finds them without knowing Funcky's Sequence class. The rule is the upgrade path should a later major version retire Sequence.

How to fix violations

Replace the Sequence receiver with Enumerable. The code fix does this, keeps the arguments and type arguments, and adds using Funcky.Extensions; when the extension members are not in scope yet. It supports fix-all.

Examples

Disallowed

IEnumerable<int> powersOfTwo = Sequence.Successors(1, n => n * 2);
IReadOnlyList<string> tags = Sequence.Return("a", "b");

Allowed

IEnumerable<int> powersOfTwo = Enumerable.Successors(1, n => n * 2);
IReadOnlyList<string> tags = Enumerable.Return("a", "b");

// A method group has no static counterpart of the same shape.
IEnumerable<IReadOnlyList<int>> singletons = values.Select(Sequence.Return);