{"id":24486094,"url":"https://github.com/reegeek/structlinq","last_synced_at":"2025-04-13T04:09:17.013Z","repository":{"id":37880822,"uuid":"169719064","full_name":"reegeek/StructLinq","owner":"reegeek","description":"Implementation in C# of LINQ concept with struct","archived":false,"fork":false,"pushed_at":"2024-01-19T04:30:11.000Z","size":1010,"stargazers_count":302,"open_issues_count":33,"forks_count":11,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-04-13T02:14:52.464Z","etag":null,"topics":["allocation-free","csharp","fast","linq","struct"],"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/reegeek.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"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}},"created_at":"2019-02-08T10:35:44.000Z","updated_at":"2025-01-19T16:11:22.000Z","dependencies_parsed_at":"2023-02-15T13:01:43.222Z","dependency_job_id":"3a533ea2-b971-481f-9e2b-d603b87aac4b","html_url":"https://github.com/reegeek/StructLinq","commit_stats":null,"previous_names":[],"tags_count":31,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reegeek%2FStructLinq","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reegeek%2FStructLinq/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reegeek%2FStructLinq/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/reegeek%2FStructLinq/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/reegeek","download_url":"https://codeload.github.com/reegeek/StructLinq/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248661705,"owners_count":21141450,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["allocation-free","csharp","fast","linq","struct"],"created_at":"2025-01-21T14:32:42.390Z","updated_at":"2025-04-13T04:09:16.973Z","avatar_url":"https://github.com/reegeek.png","language":"C#","readme":"# StructLinq\n[![GitHub release](https://img.shields.io/github/v/release/reegeek/StructLinq.svg?logo=GitHub)](https://github.com/reegeek/StructLinq/releases)  \n[![Nuget](https://img.shields.io/nuget/v/StructLinq)](https://www.nuget.org/packages/StructLinq/) ![Nuget](https://img.shields.io/nuget/dt/structLinq)  \n[![Build Status](https://dev.azure.com/reegeek/StrucLinq/_apis/build/status/reegeek.StructLinq?branchName=master)](https://dev.azure.com/reegeek/StrucLinq/_build/latest?definitionId=2\u0026branchName=master)\n[![continuous](https://github.com/reegeek/StructLinq/workflows/continuous/badge.svg)](https://github.com/reegeek/StructLinq/actions?query=workflow%3Acontinuous)  \n[![GitHub stars](https://img.shields.io/github/stars/reegeek/StructLinq)](https://github.com/reegeek/StructLinq/stargazers) [![GitHub forks](https://img.shields.io/github/forks/reegeek/StructLinq)](https://github.com/reegeek/StructLinq/network) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/reegeek/StructLinq/blob/master/LICENSE)\n\nImplementation in C# of LINQ concept with struct to reduce drastically memory allocation and improve performance. \nIntroduce `IRefStructEnumerable` to improve performance when element are fat struct.\n\n---\n- [Installation](#Installation)\n- [Usage](#Usage)\n- [Performances](#Performances)\n- [Features](#Features)\n  - [BCL bindings](#BCL)\n  - [Transformers](#Transformers)\n  - [Converters](#Converters)\n  - [LINQ Extensions](#LINQ-Extensions)\n  - [Other Extensions](#Other-Extensions)\n- [IRefStructEnumerable](#IRefStructEnumerable)\n---\n\n## Installation\nThis library is distributed via [NuGet](https://www.nuget.org/).\nTo install [`StructLinq`](https://www.nuget.org/packages/StructLinq/) :\n  ```\n  PM\u003e Install-Package StructLinq\n  ```\n\n## Usage\n\n`StructLinq` use massively generic concept and struct \"specialization\".\n\n```csharp\nusing StructLinq;\n \nint[] array = new [] {1, 2, 3, 4, 5};\n\nint result = array\n                .ToStructEnumerable()\n                .Where(x =\u003e (x \u0026 1) == 0, x=\u003ex)\n                .Select(x =\u003e x *2, x =\u003e x)\n                .Sum();\n```\n\n`x=\u003ex` is used to avoid boxing (and allocation) and to help generic type parameters inference.\nYou can also improve performance by using struct for Where predicate and select function.\n\n## Performances\n\nAll benchmark results are in [here](Documents/BenchmarksResults).\nFor example following linq sequence:\n ```csharp\n    list\n      .Where(x =\u003e (x \u0026 1) == 0)\n      .Select(x =\u003e x * 2)\n      .Sum();\n ```\n can be replace by:\n  ```csharp\n    list\n      .ToStructEnumerable()\n      .Where(x =\u003e (x \u0026 1) == 0)\n      .Select(x =\u003e x * 2)\n      .Sum();\n ```\n or if you want zero allocation by:\n   ```csharp\n    list\n      .ToStructEnumerable()\n      .Where(x =\u003e (x \u0026 1) == 0, x=\u003ex)\n      .Select(x =\u003e x * 2, x=\u003ex)\n      .Sum(x=\u003ex);\n ```\n or if you want zero allocation and better performance by:\n  ```csharp\n    var where = new WherePredicate();\n    var select = new SelectFunction();\n    list\n      .ToStructEnumerable()\n      .Where(ref @where, x =\u003e x)\n      .Select(ref @select, x =\u003e x, x =\u003e x)\n      .Sum(x =\u003e x);\n ```\n\n\n [Benchmark](src/StructLinq.Benchmark/ListWhereSelectSum.cs) results are:\n\n``` ini\n\nBenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042\nIntel Core i7-8750H CPU 2.20GHz (Coffee Lake), 1 CPU, 12 logical and 6 physical cores\n.NET Core SDK=5.0.101\n  [Host]     : .NET Core 5.0.1 (CoreCLR 5.0.120.57516, CoreFX 5.0.120.57516), X64 RyuJIT\n  DefaultJob : .NET Core 5.0.1 (CoreCLR 5.0.120.57516, CoreFX 5.0.120.57516), X64 RyuJIT\n\n\n```\n|                          Method |      Mean |     Error |    StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated |\n|-------------------------------- |----------:|----------:|----------:|------:|------:|------:|------:|----------:|\n|                            LINQ | 65.116 μs | 0.6153 μs | 0.5756 μs |  1.00 |     - |     - |     - |     152 B |\n|          StructLinqWithDelegate | 26.146 μs | 0.2402 μs | 0.2247 μs |  0.40 |     - |     - |     - |      96 B |\n| StructLinqWithDelegateZeroAlloc | 27.854 μs | 0.0938 μs | 0.0783 μs |  0.43 |     - |     - |     - |         - |\n|             StructLinqZeroAlloc |  6.872 μs | 0.0155 μs | 0.0137 μs |  0.11 |     - |     - |     - |         - |\n \n\n`StructLinq` is significatively faster than default `LINQ` implementation.\n\n## Features\n\nDuck typing with `foreach` is available with zero allocation for `IStructEnumerable`.\n\n### BCL\n\nFollowing class have a `StructLinq` extension method for `IStructEnumerable`:\n  - `IEnumerable\u003cT\u003e`\n  - `T[]`\n  - `List\u003cT\u003e` (in [`Struct.Linq.BCL`](https://www.nuget.org/packages/StructLinq.BCL/))\n  - `Dictionary\u003cTKey, TValue\u003e` (in [`Struct.Linq.BCL`](https://www.nuget.org/packages/StructLinq.BCL/))\n  - `Hashset\u003cT\u003e` (in [`Struct.Linq.BCL`](https://www.nuget.org/packages/StructLinq.BCL/))\n  - `ImmutableArray\u003cT\u003e` (in [`Struct.Linq.BCL`](https://www.nuget.org/packages/StructLinq.BCL/))\n\n### Converters\nFollowing converters are available for :\n  - `ToArray`\n  - `ToList` (in [`Struct.Linq.BCL`](https://www.nuget.org/packages/StructLinq.BCL/))\n  - `ToEnumerable`\n### LINQ Extensions\nFollowing extensions are available for :\n  - `Aggregate`\n  - `All`\n  - `Any`\n  - `Concat`\n  - `Contains`\n  - `Count`\n  - `Distinct`([zero allocation](Documents/BenchmarksResults/Distinct.md))\n  - `ElementAt`\n  - `ElementAtOrDefault`\n  - `Empty`\n  - `Except`([zero allocation](Documents/BenchmarksResults/Except.md))\n  - `First`\n  - `FirstOrDefault`\n  - `Intersect`([zero allocation](Documents/BenchmarksResults/Intersect.md))\n  - `Last`\n  - `LastOrDefault`\n  - `Max`\n  - `Min`\n  - `OrderBy`([zero allocation](Documents/BenchmarksResults/OrderByArrayOfInt.md))\n  - `OrderByDescending`\n  - `Range`\n  - `Repeat`\n  - `Reverse`([zero allocation](Documents/BenchmarksResults/Reverse.md))\n  - `Select`\n  - `SelectMany`\n  - `Skip`\n  - `SkipWhile`\n  - `Sum`\n  - `Take`\n  - `TakeWhile`\n  - `Union`([zero allocation](Documents/BenchmarksResults/Union.md))\t\n  - `Where`\n### Other Extensions\n  - `LongCount`\n  - `UIntCount`\n  - `Order`\n  - `TryFirst`\n\n## IRefStructEnumerable\n\n```csharp\n    public interface IRefStructEnumerable\u003cout T, out TEnumerator\u003e\n        where TEnumerator : struct, IRefStructEnumerator\u003cT\u003e\n    {\n        TEnumerator GetEnumerator();\n    }\n\n    public interface IRefStructEnumerator\u003cT\u003e\n    {\n        bool MoveNext();\n\n        void Reset();\n\n        ref T Current { get; }\n    }\n```\n `ref Current` allows to avoid copy. I should be very useful when `T` is a fat struct.\n\n Duck typing with `foreach` with `ref` is available with zero allocation for `IRefStructEnumerable`.\n\n ### BCL\n\nFollowing class have a `StructLinq` extension method for `IRefStructEnumerable`:\n  - `T[]`\n  - `List\u003cT\u003e` (in [`Struct.Linq.BCL`](https://www.nuget.org/packages/StructLinq.BCL/))\n\n  ### Converters\nFollowing converters are available for :\n  - `ToArray`\n  - `ToList` (in [`Struct.Linq.BCL`](https://www.nuget.org/packages/StructLinq.BCL/))\n  - `ToEnumerable`\n### LINQ Extensions\nFollowing extensions are available for :\n  - `All`\n  - `Any`\n  - `Concat`\n  - `Contains`\n  - `Count`\n  - `Distinct`\n  - `ElementAt`\n  - `ElementAtOrDefault`\n  - `Except`\n  - `First`\n  - `FirstOrDefault`\n  - `Intersect`\n  - `Last`\n  - `Select`\n  - `Skip`\n  - `SkipWhile`\n  - `Sum`\n  - `Take`\n  - `TakeWhile`\n  - `Union`\n  - `Where`\n### Other Extensions\n  - `LongCount`\n  - `UIntCount`\n  - `TryFirst`\n\n\n\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freegeek%2Fstructlinq","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Freegeek%2Fstructlinq","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Freegeek%2Fstructlinq/lists"}