{"id":26497545,"url":"https://github.com/cysharp/zlinq","last_synced_at":"2026-04-08T08:02:48.685Z","repository":{"id":22355213,"uuid":"25691215","full_name":"Cysharp/ZLinq","owner":"Cysharp","description":"Zero allocation LINQ with LINQ to Span, LINQ to SIMD, and LINQ to Tree (FileSystem, JSON, GameObject, etc.) for all .NET platforms and Unity, Godot.","archived":false,"fork":false,"pushed_at":"2026-03-27T02:33:45.000Z","size":9192,"stargazers_count":4988,"open_issues_count":4,"forks_count":206,"subscribers_count":75,"default_branch":"main","last_synced_at":"2026-03-31T10:36:57.970Z","etag":null,"topics":["c-sharp","linq","unity"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Cysharp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":["neuecc"]}},"created_at":"2014-10-24T14:02:03.000Z","updated_at":"2026-03-30T14:05:42.000Z","dependencies_parsed_at":"2025-03-22T02:24:10.180Z","dependency_job_id":"320f0db3-65ee-4b68-8cc1-3250ebb143e6","html_url":"https://github.com/Cysharp/ZLinq","commit_stats":null,"previous_names":["cysharp/zlinq"],"tags_count":70,"template":false,"template_full_name":null,"purl":"pkg:github/Cysharp/ZLinq","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cysharp%2FZLinq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cysharp%2FZLinq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cysharp%2FZLinq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cysharp%2FZLinq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Cysharp","download_url":"https://codeload.github.com/Cysharp/ZLinq/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Cysharp%2FZLinq/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31545909,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T16:28:08.000Z","status":"online","status_checked_at":"2026-04-08T02:00:06.127Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["c-sharp","linq","unity"],"created_at":"2025-03-20T13:43:09.774Z","updated_at":"2026-04-08T08:02:48.677Z","avatar_url":"https://github.com/Cysharp.png","language":"C#","funding_links":["https://github.com/sponsors/neuecc"],"categories":[],"sub_categories":[],"readme":"ZLinq\n===\n[![CI](https://github.com/Cysharp/ZLinq/actions/workflows/build-debug.yaml/badge.svg)](https://github.com/Cysharp/ZLinq/actions/workflows/build-debug.yaml)\n[![Benchmark](https://github.com/Cysharp/ZLinq/actions/workflows/benchmark.yaml/badge.svg)](https://github.com/Cysharp/ZLinq/actions/workflows/benchmark.yaml)\n[![NuGet](https://img.shields.io/nuget/v/ZLinq)](https://www.nuget.org/packages/ZLinq)\n[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/Cysharp/ZLinq)\n\nZero allocation LINQ with LINQ to Span, LINQ to SIMD, and LINQ to Tree (FileSystem, JSON, GameObject, etc.) for all .NET platforms(netstandard2.0, 2.1, net8, net9) and Unity, Godot.\n\n![](img/benchmarkhead.jpg)\n\nUnlike regular LINQ, ZLinq doesn't increase allocations when adding more method chains, and it also has higher basic performance. You can check various benchmark patterns at [GitHub Actions/Benchmark](https://github.com/Cysharp/ZLinq/actions/runs/19324633887). ZLinq shows high performance in almost all patterns, with some benchmarks showing overwhelming differences.\n\nAs a bonus, LINQ operators and optimizations equivalent to .NET 10 can be used in .NET Framework 4.8 (netstandard2.0) and Unity (netstandard2.1).\n\n```bash\ndotnet add package ZLinq\n```\n\n```csharp\nusing ZLinq;\n\nvar seq = source\n    .AsValueEnumerable() // only add this line\n    .Where(x =\u003e x % 2 == 0)\n    .Select(x =\u003e x * 3);\n\nforeach (var item in seq) { }\n```\n\n* **99% compatibility** with .NET 10's LINQ (including new `Shuffle`, `RightJoin`, `LeftJoin`, `Sequence`, `InfiniteSequence` operators)\n* **Zero allocation** for method chains through struct-based Enumerable via `ValueEnumerable`\n* **LINQ to Span** to full support LINQ operations on `Span\u003cT\u003e` using .NET 9/C# 13's `allows ref struct`\n* **LINQ to Tree** to extend tree-structured objects (built-in support for FileSystem, JSON, GameObject)\n* **LINQ to SIMD** to automatic application of SIMD where possible and customizable arbitrary operations\n* Optional **Drop-in replacement** Source Generator to automatically accelerate all LINQ methods\n\nIn ZLinq, we have proven high compatibility and performance by running [dotnet/runtime's System.Linq.Tests](https://github.com/Cysharp/ZLinq/tree/main/tests/System.Linq.Tests) as a drop-in replacement, passing 9000 tests.\n\n![](img/testrun.png)\n\nPreviously, value type-based LINQ implementations were often experimental, but ZLinq fully implements all methods to completely replace standard LINQ in production use, delivering high performance suitable even for demanding applications like games. The performance aspects are based on my experience with previous LINQ implementations ([linq.js](https://github.com/neuecc/linq.js/), [SimdLinq](https://github.com/Cysharp/SimdLinq/), [UniRx](https://github.com/neuecc/UniRx), [R3](https://github.com/Cysharp/R3)), zero-allocation implementations ([ZString](https://github.com/Cysharp/ZString), [ZLogger](https://github.com/Cysharp/ZLogger)), and high-performance serializers ([MessagePack-CSharp](https://github.com/MessagePack-CSharp/MessagePack-CSharp/), [MemoryPack](https://github.com/Cysharp/MemoryPack)).\n\nZLinq achieves zero-allocation LINQ implementation using the following structs and interfaces.\n\n```csharp\npublic readonly ref struct ValueEnumerable\u003cTEnumerator, T\u003e(TEnumerator enumerator)\n    where TEnumerator : struct, IValueEnumerator\u003cT\u003e, allows ref struct\n{\n    public readonly TEnumerator Enumerator = enumerator;\n}\n\npublic interface IValueEnumerator\u003cT\u003e : IDisposable\n{\n    bool TryGetNext(out T current); // as MoveNext + Current\n\n    // Optimization helper\n    bool TryGetNonEnumeratedCount(out int count);\n    bool TryGetSpan(out ReadOnlySpan\u003cT\u003e span);\n    bool TryCopyTo(scoped Span\u003cT\u003e destination, Index offset);\n}\n```\n\nBesides changing to a struct-based approach, we've integrated MoveNext and Current to reduce the number of iterator calls. Also, some operators don't need to hold Current, which allows minimizing the struct size. Additionally, being struct-based, we efficiently separate internal state by copying the Enumerator instead of using GetEnumerator. With .NET 9/C# 13 or later, `allows ref struct` enables natural integration of `Span\u003cT\u003e` into LINQ.\n\n```csharp\npublic static ValueEnumerable\u003cWhere\u003cTEnumerator, TSource\u003e, TSource\u003e Where\u003cTEnumerator, TSource\u003e(this ValueEnumerable\u003cTEnumerator, TSource\u003e source, Func\u003cTSource, Boolean\u003e predicate)\n    where TEnumerator : struct, IValueEnumerator\u003cTSource\u003e, allows ref struct\n````\n\nOperators have this method signature. C# cannot infer types from generic constraints([dotnet/csharplang#6930](https://github.com/dotnet/csharplang/discussions/6930)). Therefore, the traditional Struct LINQ approach required implementing all operator combinations as instance methods, resulting in [100,000+ methods and massive assembly sizes](https://kevinmontrose.com/2018/01/17/linqaf-replacing-linq-and-not-allocating/). However, in ZLinq, we've successfully avoided all the boilerplate method implementations by devising an approach that properly conveys types to C# compiler.\n\nAdditionally, `TryGetNonEnumeratedCount(out int count)`, `TryGetSpan(out ReadOnlySpan\u003cT\u003e span)`, and `TryCopyTo(Span\u003cT\u003e destination, Index offset)` defined in the interface itself enable flexible optimizations. To minimize assembly size, we've designed the library to achieve maximum optimization with minimal method additions. For example, `TryCopyTo` works efficiently with methods like `ToArray` when combined with `TryGetNonEnumeratedCount`. However, it also allows copying to smaller-sized destinations. By combining this with Index, we can optimize `First`, `Last`, and `ElementAt` using just `TryCopyTo` by passing a single-element Span along with an Index.\n\nIf you're interested in architecture, please read my blog post [**\"ZLinq\", a Zero-Allocation LINQ Library for .NET**](https://neuecc.medium.com/zlinq-a-zero-allocation-linq-library-for-net-1bb0a3e5c749) where I wrote the details.\n\nGetting Started\n---\nYou can install package from [NuGet/ZLinq](https://www.nuget.org/packages/ZLinq). For Unity usage, refer to the [Unity section](#unity). For Godot usage, refer to the [Godot section](#godot).\n\n```bash\ndotnet add package ZLinq\n```\n\nUse `using ZLinq;` and call `AsValueEnumerable()` on any iterable type to use ZLinq's zero-allocation LINQ.\n\n```csharp\nusing ZLinq;\n\nvar source = new int[] { 1, 2, 3, 4, 5 };\n\n// Call AsValueEnumerable to apply ZLinq\nvar seq1 = source.AsValueEnumerable().Where(x =\u003e x % 2 == 0);\n\n// Can also be applied to Span (only in .NET 9/C# 13 environments that support allows ref struct)\nSpan\u003cint\u003e span = stackalloc int[5] { 1, 2, 3, 4, 5 };\nvar seq2 = span.AsValueEnumerable().Select(x =\u003e x * x);\n```\n\nEven if it's netstandard 2.0 or below .NET 10, all operators up to .NET 10 are available.\n\nYou can method chain and foreach like regular LINQ, but there are some limitations. Please see [Difference and Limitation](#difference-and-limitation) for details. ZLinq has drop-in replacements that apply ZLinq without needing to call `AsValueEnumerable()`. For more information, see [Drop-in replacement](#drop-in-replacement). Detailed information about [LINQ to Tree](#linq-to-tree) for LINQ-ifying tree structures (FileSystems and JSON) and [LINQ to SIMD](#linq-to-simd) for expanding SIMD application range can be found in their respective sections.\n\nAdditional Operators\n---\nIn ZLinq, we prioritize compatibility, so we try to minimize adding custom operators. However, the following methods have been added to enable efficient processing with zero allocation:\n\n### `AsValueEnumerable()`\n\nConverts existing collections to a type that can be chained with ZLinq. Any `IEnumerable\u003cT\u003e` can be converted, but for the following types, conversion is done with zero allocation without `IEnumerable\u003cT\u003e.GetEnumerator()` allocation. Standard supported types are `T[]`, `List\u003cT\u003e`, `ArraySegment\u003cT\u003e`, `Memory\u003cT\u003e`, `ReadOnlyMemory\u003cT\u003e`, `ReadOnlySequence\u003cT\u003e`, `Dictionary\u003cTKey, TValue\u003e`, `Queue\u003cT\u003e`, `Stack\u003cT\u003e`, `LinkedList\u003cT\u003e`, `HashSet\u003cT\u003e`, `ImmutableArray\u003cT\u003e`, `Span\u003cT\u003e`, `ReadOnlySpan\u003cT\u003e`. However, conversion from `ImmutableArray\u003cT\u003e` requires `.NET 8` or higher, and conversion from `Span\u003cT\u003e`, `ReadOnlySpan\u003cT\u003e` requires `.NET 9` or higher.\n\nWhen a type is declared as `IEnumerable\u003cT\u003e` or `ICollection\u003cT\u003e` rather than concrete types like `T[]` or `List\u003cT\u003e`, generally additional allocations occur when using foreach. In `ZLinq`, even when these interfaces are declared, if the actual type is `T[]` or `List\u003cT\u003e`, processing is performed with zero allocation.\n\nConvert from `System.Collections.IEnumerable` is also supported. In that case, using `AsValueEnumerable()` without specifying a type converts to `ValueEnumerable\u003c, object\u003e`, but you can also cast it simultaneously by `AsValueEnumerable\u003cT\u003e()`.\n\n```csharp\nIEnumerable nonGenericCollection = default!;\nnonGenericCollection.AsValueEnumerable(); // ValueEnumerable\u003c, object\u003e\nnonGenericCollection.AsValueEnumerable\u003cint\u003e(); // ValueEnumerable\u003c, int\u003e\n```\n\n### `ValueEnumerable.Range()`, `ValueEnumerable.Repeat()`, `ValueEnumerable.Empty()`\n\n`ValueEnumerable.Range` operates more efficiently when handling with `ZLinq` than `Enumerable.Range().AsValueEnumerable()`. The same applies to `Repeat` and `Empty`. The Range can also handle step increments, `INumber\u003cT\u003e`, `DateTime`, and more. Please refer to the [Range and Sequence](#range-and-sequence) section for details.\n\n### `Sequence`, `InfiniteSequence` for all .NET Platforms\n\n`Sequence` and `InfiniteSequence` were added in .NET 10. They require `INumber\u003cT\u003e`, but `INumber\u003cT\u003e` was introduced in `.NET 7`. `ZLinq` implements `INumber\u003cT\u003e` methods the same as standard LINQ, but additionaly adds primitive type overloads(`byte/sbyte/ushort/char/short/uint/int/ulong/long/float/double/decimal`) to support all .NET Platforms(includes .NET Standard 2.0). Additionaly, as a bonus, `DateTime` and `DateTimeOffset` overload exists.\n\n### `Average() : where INumber\u003cT\u003e`, `Sum() : where INumber\u003cT\u003e`\n\nSystem.Linq's `Average` and `Sum` are limited to certain primitive types, but ZLinq extends them to all `INumber\u003cT\u003e` types. In `.NET 8` or higher, where constraints are included, but for others (netstandard2.0, 2.1), runtime errors will occur when called with non-primitive target types.\n\n### `SumUnchecked()`\n\n`Sum` is `checked`, but checking for overflow during SIMD execution creates performance overhead. `SumUnchecked` skips overflow checking to achieve maximum SIMD aggregation performance. Note that this requires `.NET 8` or higher, and SIMD-supported types are `sbyte`, `short`, `int`, `long`, `byte`, `ushort`, `uint`, `ulong`, `double`, and the source must be able to get a Span (`TryGetSpan` returns true).\n\n### `AggregateBy`, `CountBy` constraints\n\n.NET 9 `AggregateBy` and `CountBy` has `TKey : notnull` constraints. However, this is due to internal implementation considerations, and it lacks consistency with traditional operators such as Lookup and Join. Therefore, in ZLinq, the notnull constraint was removed.\n\n### `int CopyTo(Span\u003cT\u003e destination)`, `void CopyTo(List\u003cT\u003e list)`\n\n`CopyTo` can be used to avoid allocation of the return collection unlike `ToArray` or `ToList`. `int CopyTo(Span\u003cT\u003e destination)` allows the destination to be smaller than the source, returning the number of elements copied. `void CopyTo(List\u003cT\u003e list)` clears the list and then fills it with elements from the source, so the destination size is list.Count.\n\n### `PooledArray\u003cTSource\u003e ToArrayPool()`\n\nThe returned array is rented from `ArrayPool\u003cTSource\u003e.Shared`. `PooledArray\u003cTSource\u003e` defines `.Span`, `.Memory`, `.AsEnumerable()` and other methods. These allow you to pass a `ValueEnumerable` to another method while minimizing allocations. Additionally, through `.AsValueEnumerable()`, you can call `ZLinq` methods, which is useful for temporarily materializing computationally expensive operations. Being `IDisposable`, you can return the borrowed array to `ArrayPool\u003cTSource\u003e.Shared` using the `using` statement.\n\n```csharp\nusing var array = ValueEnumerable.Range(1, 1000).ToArrayPool();\n\nvar size = array.Size; // same as Length/Count in other types\nvar span = array.Span;\nvar memory = array.Memory;\nvar arraySegment = array.ArraySegment;\nvar enumerable = array.AsEnumerable();\nvar valueEnumerable = array.AsValueEnumerable();\n```\n\nFor performance reasons to reduce allocations, `PooledArray\u003cTSource\u003e` is a `struct`. This creates a risk of returning the same array multiple times due to boxing or copying. Also, ArrayPool is not suitable for long-term array storage. It is recommended to simply use `ToArrayPool()` with `using` and keep the lifetime short.\n\nIf you absolutely need the raw internal array, you can `Deconstruct` it to `(T[] Array, int Size)`. After deconstructing, ownership is considered transferred, and all methods of `PooledArray\u003cTSource\u003e` become unavailable.\n\n### `JoinToString(char|string separator)`\n\nSince `ZLinq` is not `IEnumerable\u003cT\u003e`, it cannot be passed to `String.Join`. `JoinToString` provides the same functionality as `String.Join`, returning a string joined with the separator.\n\nRange and Sequence\n---\nIn .NET 10, `Enumerable.Sequence` and `Enumerable.InfiniteSequence` have been added, improving the expressiveness of Range operations. ZLinq also implements these, so they can be used. However, since they require `INumber\u003cT\u003e` and `IAdditionalOperator\u003cT\u003e`, they are limited to .NET 8 and above. ZLinq makes `Sequence` and `InfiniteSequence` available on all .NET Platforms (including .NET Standard 2.0) by adding primitive type overloads (`byte/sbyte/ushort/char/short/uint/int/ulong/long/float/double/decimal`).\n\nIn ZLinq, for .NET 8 and above, `Range` also supports `INumber\u003cT\u003e`, and step overloads have been added.\n\n```csharp\npublic static ValueEnumerable\u003cFromRange\u003cT, T\u003e, T\u003e Range\u003cT\u003e(T start, int count)\n    where T : INumberBase\u003cT\u003e\n\npublic static ValueEnumerable\u003cFromRange\u003cT, TStep\u003e, T\u003e Range\u003cT, TStep\u003e(T start, int count, TStep step)\n    where T : IAdditionOperators\u003cT, TStep, T\u003e\n```\n\nFurthermore, `Range`, `Sequence`, and `InfiniteSequence` have added overloads for `DateTime` and `DateTimeOffset`. These are available on all target platforms.\n\n```csharp\npublic static ValueEnumerable\u003cFromRangeDateTime, DateTime\u003e Range(DateTime start, int count, TimeSpan step) =\u003e new(new(start, count, step));\npublic static ValueEnumerable\u003cFromRangeDateTimeOffset, DateTimeOffset\u003e Range(DateTimeOffset start, int count, TimeSpan step) =\u003e new(new(start, count, step));\npublic static ValueEnumerable\u003cFromSequenceDateTime, DateTime\u003e Sequence(DateTime start, DateTime endInclusive, TimeSpan step)\npublic static ValueEnumerable\u003cFromSequenceDateTimeOffset, DateTimeOffset\u003e Sequence(DateTimeOffset start, DateTimeOffset endInclusive, TimeSpan step)\npublic static ValueEnumerable\u003cFromInfiniteSequenceDateTime, DateTime\u003e InfiniteSequence(DateTime start, TimeSpan step)\npublic static ValueEnumerable\u003cFromInfiniteSequenceDateTimeOffset, DateTimeOffset\u003e InfiniteSequence(DateTimeOffset start, TimeSpan step)\n```\n\n```csharp\n// DateTime/DateTimeOffset example\n\n// 5/13, 5/14, 5/15, 5/16, 5/17, 5/18, 5/19\nvar daysOfweek = ValueEnumerable.Range(DateTime.Now, 7, TimeSpan.FromDays(1));\n\n// 5/1, 5/2,...,5/31\nvar now = DateTime.Now;\nvar calendarOfThisMonth = ValueEnumerable.Range(new DateTime(now.Year, now.Month, 1), DateTime.DaysInMonth(now.Year, now.Month), TimeSpan.FromDays(1));\n\n// 5/1, 5/2,...,\nvar endlessDate = ValueEnumerable.InfiniteSequence(DateTime.Now, TimeSpan.FromDays(1));\n```\n\nDifference and Limitation\n---\nFor .NET 9 and above, `ValueEnumerable\u003cT\u003e` is a `ref struct` and cannot be converted to `IEnumerable\u003cT\u003e`. To ensure compatibility when upgrading, `AsEnumerable` is not provided by default even for versions prior to .NET 9.\n\nSince `ValueEnumerable\u003cT\u003e` is not an `IEnumerable\u003cT\u003e`, it cannot be passed to methods that require `IEnumerable\u003cT\u003e`. It's also difficult to pass it to other methods due to the complex type signatures required by generics (implementation is explained in the [Custom Extensions](#custom-extensions) section). Using `ToArray()` is one solution, but this can cause unnecessary allocations in some cases. For temporary use, you can call `ToArrayPool` to pass to methods that require `IEnumerable\u003cT\u003e` without allocations. However, be careful that this `IEnumerable\u003cT\u003e` will be returned within the using scope, so you must ensure it doesn't leak outside the scope (storing it in a field is not allowed).\n\n`String.Join` has overloads for both `IEnumerable\u003cstring\u003e` and `params object[]`. Passing `ValueEnumerable\u003cT\u003e` directly will select the `object[]` overload, which may not give the desired result. In this case, use the `JoinToString` operator instead.\n\n`ValueEnumerable\u003cT\u003e` is a struct, and its size increases slightly with each method chain. With many chained methods, copy costs can become significant. When iterating over small collections, these copy costs can outweigh the benefits, causing performance to be worse than standard LINQ. However, this is only an issue with extremely long method chains and small iteration counts, so it's rarely a practical concern.\n\n`ValueEnumerable\u003cT\u003e` is `ref struct` in .NET 9 or above, this means that it cannot span across yield or await. Using yield or await inside foreach also fails and shows compilation errors. If enumeration is needed, please materialize the data using methods like [ToArrayPool](#pooledarraytsource-toarraypool).\n\nEach chain operation returns a different type, so you cannot reassign to the same variable. For example, code that continuously reassigns `Concat` in a for loop cannot be implemented.\n\nIn .NET 8 and above, the `Sum` and `Average` methods for `double` use SIMD processing, which performs parallel processing based on SIMD width. This results in calculation errors that differ from normal ones due to the different order of addition.\n\nDrop-in replacement\n---\nWhen introducing `ZLinq.DropInGenerator`, you can automatically use ZLinq for all LINQ methods without calling `AsValueEnumerable()`.\n\n```bash\ndotnet add package ZLinq.DropInGenerator\n```\n\n![](img/dropin.jpg)\n\nIt works by using a Source Generator to add extension methods for each type that take priority, making `ZLinq` methods be selected instead of System.Linq when the same name and arguments are used.\nAfter installing the package, you need to configure it with an assembly attribute.\n\n```csharp\n[assembly: ZLinq.ZLinqDropInAttribute(\"ZLinq\", ZLinq.DropInGenerateTypes.Array)]\n```\n\n`generateNamespace` is the namespace for the generated code, and `DropInGenerateTypes` selects the target types.\n`DropInGenerateTypes` allows you to choose from `Array`, `Span` (Span/ReadOnlySpan), `Memory` (Memory/ReadOnlyMemory), `List`, and `Enumerable` (IEnumerable).\nThese are Flags, so you can combine them, such as `DropInGenerateTypes.Array | DropInGenerateTypes.Span`.\nThere are also predefined combinations: `Collection = Array | Span | Memory | List` and `Everything = Array | Span | Memory | List | Enumerable`.\n\nWhen using `DropInGenerateTypes.Enumerable`, which generates extension methods for `IEnumerable\u003cT\u003e`, you need to make `generateNamespace` global as a namespace priority.\nFor example:\n\n```csharp\n[assembly: ZLinq.ZLinqDropInAttribute(\"\", ZLinq.DropInGenerateTypes.Everything)]\n```\n\nThis is the most aggressive configuration, causing all LINQ methods to be processed by ZLinq, and making it impossible to use normal LINQ methods (if Enumerable is not included, you can call AsEnumerable() to execute with System.Linq).\n\nIt's better to use application's default namespace rather than globally, as this allows you to switch between normal LINQ using namespaces. This approach is recommended when you need to target `Enumerable`.\n\n```csharp\nusing ZLinq;\n\n[assembly: ZLinqDropInAttribute(\"MyApp\", DropInGenerateTypes.Everything)]\n\n// namespace under MyApp\nnamespace MyApp.Foo\n{\n    public class Bar\n    {\n        public static void Foo(IEnumerable\u003cint\u003e source)\n        {\n            // ZLinq ValueEnumerable\u003cT\u003e\n            var seq = source.Select(x =\u003e x * 2).Shuffle();\n            using var e = seq.Enumerator;\n            while (e.TryGetNext(out var current))\n            {\n                Console.WriteLine(current);\n            }\n        }\n    }\n}\n\n// not under MyApp namespace\nnamespace NotMyApp\n{\n    public class Baz\n    {\n        public static void Foo(IEnumerable\u003cint\u003e source)\n        {\n            // IEnumerable\u003cT\u003e\n            var seq = source.Select(x =\u003e x * 2); // .Shuffle();\n            using var e = seq.GetEnumerator();\n            while (e.MoveNext())\n            {\n                Console.WriteLine(e.Current);\n            }\n        }\n    }\n}\n```\n\nZLinq is powerful and in many cases it performs better than regular LINQ, but it also has its limitations. For more information, please refer to [Difference and Limitation](#difference-and-limitation). When you are not familiar with it, we recommend that you use `DropInGenerateTypes.Collection` instead of `DropInGenerateTypes.Everything`.\n\nOther options for `ZLinqDropInAttribute` include `GenerateAsPublic`, `ConditionalCompilationSymbols`, and `DisableEmitSource`.\n\n```csharp\n[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false, Inherited = false)]\npublic sealed class ZLinqDropInAttribute : Attribute\n{\n    /// \u003csummary\u003e\n    /// Gets the namespace where the generated LINQ implementations will be placed.\n    /// If empty, the implementations will be generated in the global namespace.\n    /// \u003c/summary\u003e\n    public string GenerateNamespace { get; }\n\n    /// \u003csummary\u003e\n    /// Gets the types of collections for which LINQ implementations should be generated.\n    /// \u003c/summary\u003e\n    public DropInGenerateTypes DropInGenerateTypes { get; }\n\n    /// \u003csummary\u003e\n    /// Gets whether the generated LINQ implementations should be public.\n    /// When true, the implementations will be generated with public visibility.\n    /// When false (default), the implementations will be generated with internal visibility.\n    /// \u003c/summary\u003e\n    public bool GenerateAsPublic { get; set; }\n\n    /// \u003csummary\u003e\n    /// Gets or sets the conditional compilation symbols to wrap the generated code with #if directives.\n    /// If specified, the generated code will be wrapped in #if/#endif directives using these symbols.\n    /// \u003c/summary\u003e\n    public string? ConditionalCompilationSymbols { get; set; }\n\n    /// \u003csummary\u003e\n    /// Gets or sets whether to disable source generation in emitted code.\n    /// When true, the source code comments will not be included in the generated code.\n    /// When false (default), source code comments will be included in the generated code.\n    /// \u003c/summary\u003e\n    public bool DisableEmitSource { get; set; }\n\n    /// \u003csummary\u003e\n    /// Initializes a new instance of the \u003csee cref=\"ZLinqDropInAttribute\"/\u003e class.\n    /// \u003c/summary\u003e\n    /// \u003cparam name=\"generateNamespace\"\u003eThe namespace where the generated LINQ implementations will be placed. If empty, place to global.\u003c/param\u003e\n    /// \u003cparam name=\"dropInGenerateTypes\"\u003eThe types of collections for which LINQ implementations should be generated.\u003c/param\u003e\n    public ZLinqDropInAttribute(string generateNamespace, DropInGenerateTypes dropInGenerateTypes)\n    {\n        GenerateNamespace = generateNamespace;\n        DropInGenerateTypes = dropInGenerateTypes;\n    }\n}\n```\n\nTo support DropIn types other than `DropInGenerateTypes`, you can use `ZLinqDropInExternalExtensionAttribute`. This attribute allows you to generate DropIn for any type by specifying its fully qualified name. For example, to add support for `IReadOnlyCollection\u003cT\u003e` and `IReadOnlyList\u003cT\u003e`, write:\n\n```csharp\n// T must be written as `1 (metadata-name). For nested types, connect with +\n[assembly: ZLinqDropInExternalExtension(\"ZLinq\", \"System.Collections.Generic.IReadOnlyCollection`1\")]\n[assembly: ZLinqDropInExternalExtension(\"ZLinq\", \"System.Collections.Generic.IReadOnlyList`1\")]\n```\n\nFor types that support `IValueEnumerator\u003cT\u003e` through `AsValueEnumerable()`, specify the ValueEnumerator type name as the second argument. For example, with `ImmutableArray\u003cT\u003e`:\n\n```csharp\n[assembly: ZLinqDropInExternalExtension(\"ZLinq\", \"System.Collections.Immutable.ImmutableArray`1\", \"ZLinq.Linq.FromImmutableArray`1\")]\n```\n\nThis allows all operators to be processed by ZLinq using an optimized type.\n\nIf you want to make your custom collection types DropIn compatible, you can embed them in your assembly using `[ZLinqDropInExtension]`.\n\n```csharp\n[ZLinqDropInExtension]\npublic class AddOnlyIntList : IEnumerable\u003cint\u003e\n{\n    List\u003cint\u003e list = new List\u003cint\u003e();\n\n    public void Add(int x) =\u003e list.Add(x);\n\n    public IEnumerator\u003cint\u003e GetEnumerator() =\u003e list.GetEnumerator();\n    IEnumerator IEnumerable.GetEnumerator() =\u003e list.GetEnumerator();\n}\n```\n\nThis generates a `public static partial class AddOnlyIntListZLinqDropInExtensions` in the same namespace, overriding all LINQ operators with ZLinq. This works with generic types as well:\n\n```csharp\n[ZLinqDropInExtension]\npublic class AddOnlyList\u003cT\u003e : IEnumerable\u003cT\u003e\n```\n\nWhile `[ZLinqDropInExtension]` works with classes implementing `IEnumerable\u003cT\u003e`, implementing `IValueEnumerable\u003cTEnumerator, T\u003e` provides zero-allocation optimization for ZLinq:\n\n```csharp\n[ZLinqDropInExtension]\npublic class AddOnlyIntList2 : IValueEnumerable\u003cAddOnlyIntList2.Enumerator, int\u003e\n{\n    List\u003cint\u003e list = new List\u003cint\u003e();\n\n    public void Add(int x) =\u003e list.Add(x);\n\n    public ValueEnumerable\u003cFromValueEnumerable\u003cEnumerator, int\u003e, int\u003e AsValueEnumerable()\n    {\n        // you need to write new(new(new())) magic.\n        return new(new(new(list)));\n    }\n\n    // `public` struct enumerator\n    public struct Enumerator(List\u003cint\u003e source) : IValueEnumerator\u003cint\u003e\n    {\n        int index;\n\n        public bool TryGetNonEnumeratedCount(out int count)\n        {\n            count = source.Count;\n            return true;\n        }\n\n        public bool TryGetSpan(out ReadOnlySpan\u003cint\u003e span)\n        {\n            span = CollectionsMarshal.AsSpan(source);\n            return true;\n        }\n\n        public bool TryCopyTo(scoped Span\u003cint\u003e destination, Index offset)\n        {\n            // Optional path: if you can not write this, always return false is ok.\n            ReadOnlySpan\u003cint\u003e span = CollectionsMarshal.AsSpan(source);\n            if (ZLinq.Internal.EnumeratorHelper.TryGetSlice(span, offset, destination.Length, out var slice))\n            {\n                slice.CopyTo(destination);\n                return true;\n\n            }\n            return false;\n        }\n\n        public bool TryGetNext(out int current)\n        {\n            if (index \u003c source.Count)\n            {\n                current = source[index];\n                index++;\n                return true;\n            }\n\n            current = default;\n            return false;\n        }\n\n        public void Dispose() { }\n    }\n}\n```\n\nIn this case, implementing `IEnumerable\u003cT\u003e` is not necessary. If a collection implements both `IEnumerable\u003cT\u003e` and `IValueEnumerable\u003cTEnumerator, T\u003e`, the latter takes precedence.\n\nLINQ to Tree\n---\nLINQ to XML introduced the concept of querying around axes to C#. Even if you don't use XML, similar APIs are incorporated into Roslyn and effectively used for exploring SyntaxTrees. ZLinq extends this concept to make it applicable to anything that can be considered a Tree, allowing `Ancestors`, `Children`, `Descendants`, `BeforeSelf`, and `AfterSelf` to be applied.\n\n![](img/axis.jpg)\n\nSpecifically, by defining a struct that implements the following interface, it becomes iterable:\n\n```csharp\npublic interface ITraverser\u003cTTraverser, T\u003e : IDisposable\n    where TTraverser : struct, ITraverser\u003cTTraverser, T\u003e // self\n{\n    T Origin { get; }\n    TTraverser ConvertToTraverser(T next); // for Descendants\n    bool TryGetHasChild(out bool hasChild); // optional: optimize use for Descendants\n    bool TryGetChildCount(out int count);   // optional: optimize use for Children\n    bool TryGetParent(out T parent); // for Ancestors\n    bool TryGetNextChild(out T child); // for Children | Descendants\n    bool TryGetNextSibling(out T next); // for AfterSelf\n    bool TryGetPreviousSibling(out T previous); // BeforeSelf\n}\n```\n\nStandard packages are available for FileSystemInfo and JsonNode. For Unity, it's applicable to GameObject and Transform.\n\n### FileSystem\n\n```bash\ndotnet add package ZLinq.FileSystem\n```\n\n```csharp\nusing ZLinq;\n\nvar root = new DirectoryInfo(\"C:\\\\Program Files (x86)\\\\Steam\");\n\n// FileSystemInfo(FileInfo/DirectoryInfo) can call `Ancestors`, `Children`, `Descendants`, `BeforeSelf`, `AfterSelf`\nvar allDlls = root\n    .Descendants()\n    .OfType\u003cFileInfo\u003e()\n    .Where(x =\u003e x.Extension == \".dll\");\n\nvar grouped = allDlls\n    .GroupBy(x =\u003e x.Name)\n    .Select(x =\u003e new { FileName = x.Key, Count = x.Count() })\n    .OrderByDescending(x =\u003e x.Count);\n\nforeach (var item in grouped)\n{\n    Console.WriteLine(item);\n}\n```\n\n### JSON(System.Text.Json)\n\n```bash\ndotnet add package ZLinq.Json\n```\n\n```csharp\nusing ZLinq;\n\n// System.Text.Json's JsonNode is the target of LINQ to JSON(not JsonDocument/JsonElement).\nvar json = JsonNode.Parse(\"\"\"\n{\n    \"nesting\": {\n      \"level1\": {\n        \"description\": \"First level of nesting\",\n        \"value\": 100,\n        \"level2\": {\n          \"description\": \"Second level of nesting\",\n          \"flags\": [true, false, true],\n          \"level3\": {\n            \"description\": \"Third level of nesting\",\n            \"coordinates\": {\n              \"x\": 10.5,\n              \"y\": 20.75,\n              \"z\": -5.0\n            },\n            \"level4\": {\n              \"description\": \"Fourth level of nesting\",\n              \"metadata\": {\n                \"created\": \"2025-02-15T14:30:00Z\",\n                \"modified\": null,\n                \"version\": 2.1\n              },\n              \"level5\": {\n                \"description\": \"Fifth level of nesting\",\n                \"settings\": {\n                  \"enabled\": true,\n                  \"threshold\": 0.85,\n                  \"options\": [\"fast\", \"accurate\", \"balanced\"],\n                  \"config\": {\n                    \"timeout\": 30000,\n                    \"retries\": 3,\n                    \"deepSetting\": {\n                      \"algorithm\": \"advanced\",\n                      \"parameters\": [1, 1, 2, 3, 5, 8, 13]\n                    }\n                  }\n                }\n              }\n            }\n          }\n        }\n      }\n    }\n}\n\"\"\");\n\n// JsonNode\nvar origin = json![\"nesting\"]![\"level1\"]![\"level2\"]!;\n\n// JsonNode axis, Children, Descendants, Anestors, BeforeSelf, AfterSelf and ***Self.\nforeach (var item in origin.Descendants().Select(x =\u003e x.Node).OfType\u003cJsonArray\u003e())\n{\n    // [true, false, true], [\"fast\", \"accurate\", \"balanced\"], [1, 1, 2, 3, 5, 8, 13]\n    Console.WriteLine(item.ToJsonString(JsonSerializerOptions.Web));\n}\n```\n\n### GameObject/Transform(Unity)\n\nsee: [unity](#unity) section.\n\nLINQ to SIMD\n---\nIn .NET 8 and above, there are operators that apply SIMD when `ValueEnumerable\u003cT\u003e.TryGetSpan` returns true. The scope of application is wider than in regular System.Linq.\n\n* **Range** to ToArray/ToList/CopyTo/etc...\n* **Repeat** for `unmanaged struct` and `size is power of 2` to ToArray/ToList/CopyTo/etc...\n* **Sum** for `sbyte`, `short`, `int`, `long`, `byte`, `ushort`, `uint`, `ulong`, `double`\n* **SumUnchecked** for `sbyte`, `short`, `int`, `long`, `byte`, `ushort`, `uint`, `ulong`, `double`\n* **Average** for `sbyte`, `short`, `int`, `long`, `byte`, `ushort`, `uint`, `ulong`, `double`\n* **Max** for `byte`, `sbyte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `nint`, `nuint`, `Int128`, `UInt128`\n* **Min** for `byte`, `sbyte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `nint`, `nuint`, `Int128`, `UInt128`\n* **Contains** for `byte`, `sbyte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `bool`, `char`, `nint`, `nuint`\n* **SequenceEqual** for `byte`, `sbyte`, `short`, `ushort`, `int`, `uint`, `long`, `ulong`, `bool`, `char`, `nint`, `nuint`\n\n`Sum` performs calculations as checked, but if you don't need to worry about overflow, using `SumUnchecked` is faster.\n\n| Method            | N     | Mean          | Allocated |\n|------------------ |------ |--------------:|----------:|\n| ForLoop           | 16384 | 25,198.556 ns |         - |\n| SystemLinqSum     | 16384 |  1,402.259 ns |         - |\n| ZLinqSum          | 16384 |  1,351.449 ns |         - |\n| ZLinqSumUnchecked | 16384 |    721.832 ns |         - |\n\nBy using `ZLinq.Simd` in your using statements, you can call `.AsVectorizable()` on `T[]` or `Span\u003cT\u003e` or `ReadOnlySpan\u003cT\u003e`, which allows you to use `Sum`, `SumUnchecked`, `Average`, `Max`, `Min`, `Contains`, and `SequenceEqual`. This explicitly indicates execution with SIMD regardless of the LINQ chain state (though type checking is ambiguous so processing might occur in a normal loop, and if `Vector.IsHardwareAccelerated \u0026\u0026 Vector\u003cT\u003e.IsSupported` is false, normal loop processing will be used).\n\nFrom `int[]` or `Span\u003cint\u003e`, you can call `VectorizedFillRange`. This is equivalent to `ValueEunmerable.Range().CopyTo()` and allows you to quickly generate sequential numbers through SIMD processing.\n\n| Method | Mean       | Allocated |\n|------- |-----------:|----------:|\n| Range  |   540.0 ns |         - |\n| For    | 6,228.9 ns |         - |\n\n### `VectorizedUpdate`\n\nIn ZLinq, you can perform relatively flexible vectorized loop processing using `Func`. With `T[]` and `Span\u003cT\u003e`, you can use the `VectorizedUpdate` method. By writing two lambda expressions - `Func\u003cVector\u003cT\u003e, Vector\u003cT\u003e\u003e vectorFunc` for vector operations and `Func\u003cT, T\u003e func` for handling remainder elements - you can perform loop update processing at SIMD width.\n\n```csharp\nusing ZLinq.Simd; // needs using\n\nint[] source = Enumerable.Range(0, 10000).ToArray();\n\n[Benchmark]\npublic void For()\n{\n    for (int i = 0; i \u003c source.Length; i++)\n    {\n        source[i] = source[i] * 10;\n    }\n}\n\n[Benchmark]\npublic void VectorizedUpdate()\n{\n    // arg1: Vector\u003cint\u003e =\u003e Vector\u003cint\u003e\n    // arg2: int =\u003e int\n    source.VectorizedUpdate(static x =\u003e x * 10, static x =\u003e x * 10);\n}\n```\n\n| Method           | N     | Mean       | Error    | StdDev  | Allocated |\n|----------------- |------ |-----------:|---------:|--------:|----------:|\n| For              | 10000 | 4,560.5 ns | 67.24 ns | 3.69 ns |         - |\n| VectorizedUpdate | 10000 |   558.9 ns |  6.42 ns | 0.35 ns |         - |\n\nThere is delegate overhead when compared to writing everything inline, but processing can be faster than using for-loops. However, this varies case by case, so please take measurements in advance based on your data volume and method content. Of course, if you're seeking the best possible performance, you should write code inline.\n\n### Vectorizable Methods\n\nYou can convert from `T[]` or `Span\u003cT\u003e` or `ReadOnlySpan\u003cT\u003e` to `Vectorizable\u003cT\u003e` using `AsVectorizable()`, which allows you to use `Aggregate`, `All`, `Any`, `Count`, `Select`, and `Zip` methods that accept a `Func` as an argument.\n\n* `Aggregate`\n\n```csharp\nsource.AsVectorizable().Aggregate((x, y) =\u003e Vector.Min(x, y), (x, y) =\u003e Math.Min(x, y))\n```\n\n* `All`\n\n```csharp\nsource.AsVectorizable().All(x =\u003e Vector.GreaterThanAll(x, new(5000)), x =\u003e x \u003e 5000);\n```\n\n* `Any`\n\n```csharp\nsource.AsVectorizable().Any(x =\u003e Vector.LessThanAll(x, new(5000)), x =\u003e x \u003c 5000);\n```\n\n* `Count`\n\n```csharp\nsource.AsVectorizable().Count(x =\u003e Vector.GreaterThan(x, new(5000)), x =\u003e x \u003e 5000);\n```\n\n| Method            | Mean        | Error    | StdDev  | Allocated |\n|------------------ |------------:|---------:|--------:|----------:|\n| VectorizableCount |  1,048.4 ns | 39.39 ns | 2.16 ns |         - |\n| LinqCount         | 10,909.3 ns | 54.79 ns | 3.00 ns |         - |\n\n* `Select` -\u003e `ToArray` or `CopyTo`\n\n```csharp\nsource.AsVectorizable().Select(x =\u003e x * 3, x =\u003e x * 3).ToArray();\nsource.AsVectorizable().Select(x =\u003e x * 3, x =\u003e x * 3).CopyTo(destination);\n```\n\n* `Zip` -\u003e `ToArray` or `CopyTo`\n\n```csharp\n// Zip2\narray1.AsVectorizable().Zip(array2, (x, y) =\u003e x + y, (x, y) =\u003e x + y).CopyTo(destination);\narray1.AsVectorizable().Zip(array2, (x, y) =\u003e x + y, (x, y) =\u003e x + y).ToArray();\n\n// Zip3\narray1.AsVectorizable().Zip(array2, array3, (x, y, z) =\u003e x + y + z, (x, y, z) =\u003e x + y + z).CopyTo(destination);\narray1.AsVectorizable().Zip(array2, array3, (x, y, z) =\u003e x + y + z, (x, y, z) =\u003e x + y + z).ToArray();\n```\n\n| Method                      | Mean      |\n|---------------------------- |----------:|\n| ZLinqVectorizableZipCopyTo  |  24.17 μs |\n| ZLinqVectorizableZip3CopyTo |  29.26 μs |\n| ZLinqZipCopyTo              | 329.43 μs |\n| ZLinqZip3CopyTo             | 584.69 μs |\n\n\nUnity\n---\nThere are two installation steps required to use it in Unity.\n\n1. Install `ZLinq` from NuGet using [NuGetForUnity](https://github.com/GlitchEnzo/NuGetForUnity)\nOpen Window from NuGet -\u003e Manage NuGet Packages, Search \"ZLinq\" and Press Install.\n\n2. Install the `ZLinq.Unity` package by referencing the git URL\n\n```bash\nhttps://github.com/Cysharp/ZLinq.git?path=src/ZLinq.Unity/Assets/ZLinq.Unity\n```\n\nWith the help of the Unity package, in addition to the standard ZLinq, LINQ to GameObject functionality becomes available for exploring GameObject/Transform.\n\n![](img/axis.jpg)\n\n```csharp\nusing ZLinq;\n\npublic class SampleScript : MonoBehaviour\n{\n    public Transform Origin;\n\n    void Start()\n    {\n        Debug.Log(\"Ancestors--------------\");  // Container, Root\n        foreach (var item in Origin.Ancestors()) Debug.Log(item.name);\n\n        Debug.Log(\"Children--------------\"); // Sphere_A, Sphere_B, Group, Sphere_A, Sphere_B\n        foreach (var item in Origin.Children()) Debug.Log(item.name);\n\n        Debug.Log(\"Descendants--------------\"); // Sphere_A, Sphere_B, Group, P1, Group, Sphere_B, P2, Sphere_A, Sphere_B\n        foreach (var item in Origin.Descendants()) Debug.Log(item.name);\n\n        Debug.Log(\"BeforeSelf--------------\"); // C1, C2\n        foreach (var item in Origin.BeforeSelf()) Debug.Log(item.name);\n\n        Debug.Log(\"AfterSelf--------------\");  // C3, C4\n        foreach (var item in Origin.AfterSelf()) Debug.Log(item.name);\n    }\n}\n```\n\nYou can chain query(LINQ to Objects). Also, you can filter by component using the `OfComponent\u003cT\u003e` helper.\n\n```csharp\n// all filtered(tag == \"foobar\") objects\nvar foobars = root.Descendants().Where(x =\u003e x.tag == \"foobar\");\n\n// get FooScript under self childer objects and self\nvar fooScripts = root.ChildrenAndSelf().OfComponent\u003cFooScript\u003e();\n```\n\nUI Toolkit VisualElements are also supported allowing more advanced queries\n\n```csharp\npublic class SampleScript : MonoBehaviour\n{\n    private UIDocument Document;\n\n    private void Start()\n    {\n        var noTextButtons = Document\n            .rootVisualElement\n            .Descendants()\n            .OfType\u003cButton\u003e()\n            .Where(btn =\u003e string.IsNullOrEmpty(btn.text));\n\n        foreach (var btn in noTextButtons) Debug.Log(btn.name);\n    }\n}\n```\n\nNOTE: In Unity, since .NET Standard 2.1 is referenced, SIMD is not utilized.\n\nIn .NET 9, `ValueEnumerable` is a `ref struct`, so it cannot be converted to `IEnumerable\u003cT\u003e`. However, in Unity it's a regular `struct`, making it possible to convert to `IEnumerable\u003cT\u003e`. You can improve interoperability by preparing an extension method like this:\n\n```csharp\npublic static class ZLinqExtensions\n{\n    public static IEnumerable\u003cT\u003e AsEnumerable\u003cTEnumerator, T\u003e(this ValueEnumerable\u003cTEnumerator, T\u003e valueEnumerable)\n        where TEnumerator : struct, IValueEnumerator\u003cT\u003e\n    {\n        using (var e = valueEnumerable.Enumerator)\n        {\n            while (e.TryGetNext(out var current))\n            {\n                yield return current;\n            }\n        }\n    }\n}\n```\n\nIn Unity, you can convert `NativeArray`, `NativeSlice` using `AsEnumerable()` to write queries with ZLinq. If Unity Collections(`com.unity.collections`) package version is `2.1.1` or above,  `NativeQueue`, `NativeHashSet`, `NativeText`, `FixedList32Bytes`, `FixedList64Bytes`, `FixedList128Bytes`, `FixedList512Bytes`, `FixedList4096Bytes`, `FixedString32Bytes`, `FixedString64Bytes`, `FixedString128Bytes`, `FixedString512Bytes`, and `FixedString4096Bytes` support `AsValueEnumerable()`.\n\nYou can also use drop-in replacement. Add `ZLinq.DropInGenerator` from NuGetForUnity. If you want to use DropInGenerator, the minimum supported Unity version will be `2022.3.12f1`, as it is necessary to support C# Incremental Source Generator(Compiler Version, 4.3.0).\n\nAssembly attributes need to be set for each asmdef. For example, place a `.cs` file like the following in each asmdef. The DropInGenerator is defined in the assembly attributes.\n\n```csharp\n// AssemblyAttributes.cs\nusing ZLinq;\n[assembly: ZLinqDropIn(\"MyApp\", DropInGenerateTypes.Array | DropInGenerateTypes.List)]\n```\n\nFor more details about DropInGenerator, please refer to the [Drop-in replacement](#drop-in-replacement) section.\n\nTo support Native Collections in addition to regular DropIn types, you can use `ZLinqDropInExternalExtension` as follows:\n\n```csharp\n[assembly: ZLinqDropInExternalExtension(\"ZLinq\", \"Unity.Collections.NativeArray`1\", \"ZLinq.Linq.FromNativeArray`1\")]\n[assembly: ZLinqDropInExternalExtension(\"ZLinq\", \"Unity.Collections.NativeArray`1+ReadOnly\", \"ZLinq.Linq.FromNativeArray`1\")]\n[assembly: ZLinqDropInExternalExtension(\"ZLinq\", \"Unity.Collections.NativeSlice`1\", \"ZLinq.Linq.FromNativeSlice`1\")]\n[assembly: ZLinqDropInExternalExtension(\"ZLinq\", \"Unity.Collections.NativeList`1\", \"ZLinq.Linq.FromNativeList`1\")]\n```\n\nThis is not just about Unity, but using `AsValueEnumerable()` even if only for foreach on `IEnumerable\u003cT\u003e` can sometimes reduce allocations. If the actual implementation of `IEnumerable\u003cT\u003e` is a `T[]` or `List\u003cT\u003e`, ZLinq will process it appropriately without allocations.\n\n![](img/unityforeach.png)\n\n```csharp\nvoid IterateNormal(IEnumerable\u003cint\u003e source)\n{\n    // Normally there's an allocation when getting IEnumerator\u003cT\u003e.\n    foreach (var item in source)\n    {\n\n    }\n}\n\nvoid IterateZLinq(IEnumerable\u003cint\u003e source)\n{\n    // Adding AsValueEnumerable results in 0 allocation.\n    // However, zero alloc only works when the actual implementation of IEnumerable\u003cT\u003e is an array [] or List\u003cT\u003e\n    foreach (var item in source.AsValueEnumerable())\n    {\n\n    }\n}\n```\n\nGodot\n---\nThe minimum supported Godot version will be `4.0.0`.\nYou can install ZLinq.Godot package via NuGet.\n\n```bash\ndotnet add package ZLinq.Godot\n```\n\nIn addition to the standard ZLinq, LINQ to Node functionality is available.\n\n![](img/godot.jpg)\n\n```csharp\nusing Godot;\nusing ZLinq;\n\npublic partial class SampleScript : Node2D\n{\n    public override void _Ready()\n    {\n        var origin = GetNode\u003cNode2D\u003e(\"Container/Origin\");\n\n        GD.Print(\"Ancestors--------------\"); // Container, Root, root (Root Window)\n        foreach (var item in origin.Ancestors()) GD.Print(item.Name);\n\n        GD.Print(\"Children--------------\"); // Sphere_A, Sphere_B, Group, Sphere_A, Sphere_B\n        foreach (var item in origin.Children()) GD.Print(item.Name);\n\n        GD.Print(\"Descendants--------------\"); // Sphere_A, Sphere_B, Group, P1, Group, Sphere_B, P2, Sphere_A, Sphere_B\n        foreach (var item in origin.Descendants()) GD.Print(item.Name);\n\n        GD.Print(\"BeforeSelf--------------\"); // C1, C2\n        foreach (var item in origin.BeforeSelf()) GD.Print(item.Name);\n\n        GD.Print(\"AfterSelf--------------\"); // C3, C4\n        foreach (var item in origin.AfterSelf()) GD.Print(item.Name);\n    }\n}\n\n```\n\nYou can chain query(LINQ to Objects). Also, you can filter by node type using the `OfType()`.\n\n```csharp\n// get ancestors under a Window\nvar ancestors = root.Ancestors().TakeWhile(x =\u003e x is not Window);\n// get FooScript under self childer objects and self\nvar fooScripts = root.ChildrenAndSelf().OfType\u003cFooScript\u003e();\n```\n\nCustom Extensions\n---\n\nImplementing extension methods for `IEnumerable\u003cT\u003e` is common. There are two types of operators: consuming operators like `Count` and `Sum`, and chainable operators like `Select` and `Where`. This section explains how to implement them.\n\n#### Consume Operator\n\nThe method signature is slightly more complex compared to `IEnumerable\u003cT\u003e`, requiring constraints on `TEnumerator`. For .NET 9 or later, `allows ref struct` is also needed.\n\n```csharp\npublic static class MyExtensions\n{\n    public static void Consume\u003cTEnumerator, TSource\u003e(this ValueEnumerable\u003cTEnumerator, TSource\u003e source)\n        where TEnumerator : struct, IValueEnumerator\u003cTSource\u003e\n#if NET9_0_OR_GREATER\n        , allows ref struct\n#endif\n    {\n        using var e = source.Enumerator; // using Enumerator\n\n        while (e.TryGetNext(out var current)) // MoveNext + Current\n        {\n        }\n    }\n}\n```\n\nInstead of `GetEnumerator()`, use `Enumerator`, and instead of `MoveNext + Current`, use `TryGetNext(out)` to consume the iterator. The Enumerator must be used with a `using` statement.\n\nConsumers can call the Enumerator's optimization methods: `TryGetNonEnumeratedCount`, `TryGetSpan`, and `TryCopyTo`. For example, getting a Span like this is faster than normal iteration with TryGetNext:\n\n```csharp\npublic static class MyExtensions\n{\n    public static void ForEach\u003cTEnumerator, TSource\u003e(this ValueEnumerable\u003cTEnumerator, TSource\u003e source, Action\u003cTSource\u003e action)\n        where TEnumerator : struct, IValueEnumerator\u003cTSource\u003e\n#if NET9_0_OR_GREATER\n        , allows ref struct\n#endif\n    {\n        using var e = source.Enumerator;\n\n        if (e.TryGetSpan(out var span))\n        {\n            // faster iteration\n            foreach (var item in span)\n            {\n                action(item);\n            }\n        }\n        else\n        {\n            while (e.TryGetNext(out var item))\n            {\n                action(item);\n            }\n        }\n    }\n\n    public static ImmutableArray\u003cT\u003e ToImmutableArray\u003cTEnumerator, T\u003e(this ValueEnumerable\u003cTEnumerator, T\u003e source)\n        where TEnumerator : struct, IValueEnumerator\u003cT\u003e\n#if NET9_0_OR_GREATER\n        , allows ref struct\n#endif\n    {\n        using var e = source.Enumerator;\n\n        if (e.TryGetSpan(out var span))\n        {\n            return ImmutableArray.Create(span);\n        }\n        else\n        {\n            if (e.TryGetNonEnumeratedCount(out var count))\n            {\n                var array = GC.AllocateUninitializedArray\u003cTSource\u003e(count);\n\n                if (e.TryCopyTo(array, offset: 0))\n                {\n                    return ImmutableCollectionsMarshal.AsImmutableArray(array);\n                }\n                else\n                {\n                    var i = 0;\n                    while (e.TryGetNext(out var current))\n                    {\n                        array[i] = current;\n                        i++;\n                    }\n                    return ImmutableCollectionsMarshal.AsImmutableArray(array);\n                }\n            }\n            else\n            {\n                var builder = ImmutableArray.CreateBuilder\u003cTSource\u003e();\n                while (e.TryGetNext(out var current))\n                {\n                    builder.Add(current);\n                }\n                return builder.ToImmutable();\n            }\n        }\n    }\n}\n```\n\nSince the enumerator's state changes, you cannot call other methods after calling `TryGetNext`. Also, you cannot call `TryGetNext` after `TryCopyTo` or `TryGetSpan` returns `true`.\n\n#### Custom Operator\n\nUnlike `IEnumerable\u003cT\u003e`, you can't use `yield return`, so everything must be implemented by hand, making it more difficult than Consume operators. A simple `Select` implementation looks like this. For .NET 9 or later, `IValueEnumerator\u003cT\u003e` must be implemented as a `ref struct`. Also, the accessibility must be `public` or `internal`.\n\n```csharp\npublic static class MyExtensions\n{\n    public static ValueEnumerable\u003cSimpleSelect\u003cTEnumerator, TSource, TResult\u003e, TResult\u003e SimpleSelect\u003cTEnumerator, TSource, TResult\u003e(this ValueEnumerable\u003cTEnumerator, TSource\u003e source, Func\u003cTSource, TResult\u003e selector)\n        where TEnumerator : struct, IValueEnumerator\u003cTSource\u003e\n#if NET9_0_OR_GREATER\n        , allows ref struct\n#endif\n    {\n        // ValueEnumerable is only a wrapper so unwrapping to enumerator immediately is ok.\n        // `new(new())` is `new ValueEnumerable(new SimpleSelect())`, wrap enumerator to ValueEnumerable.\n        return new(new(source.Enumerator, selector));\n    }\n}\n\n#if NET9_0_OR_GREATER\npublic ref struct\n#else\npublic struct\n#endif\n    SimpleSelect\u003cTEnumerator, TSource, TResult\u003e(TEnumerator source, Func\u003cTSource, TResult\u003e selector) : IValueEnumerator\u003cTResult\u003e\n        where TEnumerator : struct, IValueEnumerator\u003cTSource\u003e\n#if NET9_0_OR_GREATER\n        , allows ref struct\n#endif\n{\n    TEnumerator source = source; // need to store source enumerator in field explicitly (ref struct limitation)\n\n    // Having fields is allowed, but reference types must be null during initialization.\n    // For example, if you hold a reference type in the constructor, it will be shared with other Enumerators and will not work correctly.\n\n    public bool TryGetNonEnumeratedCount(out int count)\n    {\n        // If source count is not changed, return count.\n        // Select count is same as source.\n        return source.TryGetNonEnumeratedCount(out count);\n    }\n\n    public bool TryGetSpan(out ReadOnlySpan\u003cTResult\u003e span)\n    {\n        // For example, Take or Skip could return a Slice\n        span = default;\n        return false;\n    }\n\n    public bool TryCopyTo(scoped Span\u003cTResult\u003e destination, Index offset)\n    {\n        // TryCopyTo implementation needs to consider Index calculations, so it's quite complex.\n        // Also, destination can be smaller than the source size.\n        // Helper methods for calculations are available in ZLinq.Internal.EnumeratorHelper,\n        // such as TryGetSliceRange, TryGetSlice, TryGetSliceRange, TryConsumeGetAt, etc.\n        return false;\n    }\n\n    // This is the main body of the normal processing\n    public bool TryGetNext(out TResult current)\n    {\n        while (source.TryGetNext(out var value))\n        {\n            current = selector(value);\n            return true;\n        }\n\n        current = default!;\n        return false;\n    }\n\n    public void Dispose()\n    {\n        // Always dispose the source\n        source.Dispose();\n    }\n}\n```\n\nFor `TryGetNonEnumeratedCount`, `TryGetSpan`, and `TryCopyTo`, it's fine to return `false` if implementation is difficult. If state is needed (for example, Take needs to keep track of the number of calls), place it in a field, but note that you should not initialize reference types or structs containing reference types in the constructor. This is because in method chains, Enumerators are passed by copy, so reference types would share references. If you need to hold reference types, they must be initialized when `TryGetNext` is first called.\n\nAcknowledgement\n---\nSince the preview version release, we have received multiple ideas for fundamental interface revisions leading to performance improvements from [@Akeit0](https://github.com/Akeit0), and test and benchmark infrastructure from [@filzrev](https://github.com/filzrev). We are grateful for their many contributions.\n\nLicense\n---\nThis library is under MIT License.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcysharp%2Fzlinq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcysharp%2Fzlinq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcysharp%2Fzlinq/lists"}