{"id":15011684,"url":"https://github.com/netfabric/netfabric.doublylinkedlist","last_synced_at":"2025-10-06T05:01:52.301Z","repository":{"id":49855746,"uuid":"159564070","full_name":"NetFabric/NetFabric.DoublyLinkedList","owner":"NetFabric","description":"An alternative to LinkedList\u003cT\u003e with reverse operation and enumeration without allocation.","archived":false,"fork":false,"pushed_at":"2023-09-10T20:30:12.000Z","size":156,"stargazers_count":17,"open_issues_count":7,"forks_count":4,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-25T23:24:14.184Z","etag":null,"topics":["csharp","csharp-library","dotnet","dotnet-library","dotnet-standard","doubly-linked-list","doublylinkedlist","enumeration","nuget-package","sourcelink"],"latest_commit_sha":null,"homepage":null,"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/NetFabric.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":"2018-11-28T20:58:27.000Z","updated_at":"2024-04-16T11:13:14.000Z","dependencies_parsed_at":"2024-09-24T19:53:55.186Z","dependency_job_id":null,"html_url":"https://github.com/NetFabric/NetFabric.DoublyLinkedList","commit_stats":{"total_commits":72,"total_committers":4,"mean_commits":18.0,"dds":0.25,"last_synced_commit":"6ee5a97868f4460d272feadb0526d3230230ec86"},"previous_names":["netfabric/netfabric.doublelinkedlist"],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NetFabric%2FNetFabric.DoublyLinkedList","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NetFabric%2FNetFabric.DoublyLinkedList/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NetFabric%2FNetFabric.DoublyLinkedList/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NetFabric%2FNetFabric.DoublyLinkedList/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NetFabric","download_url":"https://codeload.github.com/NetFabric/NetFabric.DoublyLinkedList/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248512601,"owners_count":21116637,"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":["csharp","csharp-library","dotnet","dotnet-library","dotnet-standard","doubly-linked-list","doublylinkedlist","enumeration","nuget-package","sourcelink"],"created_at":"2024-09-24T19:41:26.449Z","updated_at":"2025-10-06T05:01:47.260Z","avatar_url":"https://github.com/NetFabric.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NetFabric.DoublyLinkedList\n\n![GitHub last commit (master)](https://img.shields.io/github/last-commit/NetFabric/NetFabric.DoublyLinkedList/master.svg?logo=github\u0026logoColor=lightgray\u0026style=popout-square)\n[![Build](https://img.shields.io/github/workflow/status/NetFabric/NetFabric.DoublyLinkedList/.NET?style=flat-square\u0026logo=github)](https://github.com/NetFabric/NetFabric.DoublyLinkedList/actions/workflows/dotnet.yml)\n[![Coverage](https://img.shields.io/coveralls/github/NetFabric/NetFabric.DoublyLinkedList/master?style=flat-square\u0026logo=coveralls)](https://coveralls.io/github/NetFabric/NetFabric.DoublyLinkedList)\n[![NuGet Version](https://img.shields.io/nuget/v/NetFabric.DoublyLinkedList.svg?style=popout-square\u0026logoColor=lightgray\u0026logo=nuget)](https://www.nuget.org/packages/NetFabric.DoublyLinkedList/)\n[![NuGet Downloads](https://img.shields.io/nuget/dt/NetFabric.DoublyLinkedList.svg?style=popout-square\u0026logoColor=lightgray\u0026logo=nuget)](https://www.nuget.org/packages/NetFabric.DoublyLinkedList/)\n\nAn alternative to the [`System.Collections.Generic.LinkedList\u003cT\u003e`](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.linkedlist-1) with reverse operation and enumeration without allocation.\n\nThe public API is very similar but the internals are very different with a more efficient implementation. \n\nNew overrides and methods were added to minimizing the memory allocations, number of loops, conditions and assignments required in multiple scenarios.\n\n## Benchmarks\n\nPerformance comparison between [`System.Collections.Generic.LinkedList\u003cT\u003e`](https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.linkedlist-1) and `DoublyLinkedList\u003cT\u003e`. \n\nThe benchmarks project is part of the repository. You can check the code and run it on your machine.\n\n### Constructor performance\n\n|                         Method | Count |         Mean |      Error |     StdDev |       Median | Ratio | RatioSD |  Gen 0 | Gen 1 | Gen 2 | Allocated |\n|------------------------------- |------ |-------------:|-----------:|-----------:|-------------:|------:|--------:|-------:|------:|------:|----------:|\n|          **LinkedList_Enumerable** |     **0** |    **12.082 ns** |  **0.3174 ns** |  **0.4942 ns** |    **12.091 ns** |  **1.00** |    **0.00** | **0.0191** |     **-** |     **-** |      **40 B** |\n|                LinkedList_List |     0 |    21.542 ns |  0.9611 ns |  2.7884 ns |    19.863 ns |  2.07 |    0.21 | 0.0382 |     - |     - |      80 B |\n|    DoublyLinkedList_Enumerable |     0 |    10.749 ns |  0.0741 ns |  0.0657 ns |    10.761 ns |  0.89 |    0.04 | 0.0191 |     - |     - |      40 B |\n|          DoublyLinkedList_List |     0 |     7.533 ns |  0.1320 ns |  0.1170 ns |     7.511 ns |  0.62 |    0.03 | 0.0191 |     - |     - |      40 B |\n| DoublyLinkedList_List_Reversed |     0 |     7.391 ns |  0.1275 ns |  0.1192 ns |     7.386 ns |  0.61 |    0.03 | 0.0191 |     - |     - |      40 B |\n|                                |       |              |            |            |              |       |         |        |       |       |           |\n|          **LinkedList_Enumerable** |    **10** |   **205.166 ns** |  **1.2539 ns** |  **1.1116 ns** |   **205.147 ns** |  **1.00** |    **0.00** | **0.2677** |     **-** |     **-** |     **560 B** |\n|                LinkedList_List |    10 |   241.563 ns |  1.7717 ns |  2.3651 ns |   241.213 ns |  1.18 |    0.01 | 0.2675 |     - |     - |     560 B |\n|    DoublyLinkedList_Enumerable |    10 |   163.873 ns |  1.8013 ns |  1.5042 ns |   163.424 ns |  0.80 |    0.01 | 0.2677 |     - |     - |     560 B |\n|          DoublyLinkedList_List |    10 |   142.060 ns |  1.3490 ns |  1.1265 ns |   142.538 ns |  0.69 |    0.01 | 0.2487 |     - |     - |     520 B |\n| DoublyLinkedList_List_Reversed |    10 |   139.378 ns |  1.0579 ns |  0.8834 ns |   139.184 ns |  0.68 |    0.00 | 0.2487 |     - |     - |     520 B |\n|                                |       |              |            |            |              |       |         |        |       |       |           |\n|          **LinkedList_Enumerable** |   **100** | **1,804.348 ns** | **16.3064 ns** | **15.2530 ns** | **1,808.247 ns** |  **1.00** |    **0.00** | **2.3327** |     **-** |     **-** |   **4,880 B** |\n|                LinkedList_List |   100 | 1,894.060 ns | 12.0334 ns | 11.2561 ns | 1,895.876 ns |  1.05 |    0.01 | 2.3327 |     - |     - |   4,880 B |\n|    DoublyLinkedList_Enumerable |   100 | 1,355.031 ns | 16.9081 ns | 14.1191 ns | 1,352.691 ns |  0.75 |    0.01 | 2.3327 |     - |     - |   4,880 B |\n|          DoublyLinkedList_List |   100 | 1,216.764 ns | 11.3984 ns | 10.6620 ns | 1,218.606 ns |  0.67 |    0.01 | 2.3136 |     - |     - |   4,840 B |\n| DoublyLinkedList_List_Reversed |   100 | 1,233.906 ns | 11.7235 ns | 10.9662 ns | 1,238.096 ns |  0.68 |    0.01 | 2.3136 |     - |     - |   4,840 B |\n\n### Enumeration performance\n\n|                           Method | Categories |  Count |     Mean |   Error |  StdDev | Ratio | RatioSD |   Gen 0 |   Gen 1 |   Gen 2 | Allocated |\n|--------------------------------- |----------- |------- |---------:|--------:|--------:|------:|--------:|--------:|--------:|--------:|----------:|\n|         LinkedList_Forward_While |    Forward | 100000 | 320.0 μs | 3.77 μs | 3.53 μs |  1.00 |    0.00 |       - |       - |       - |         - |\n|       LinkedList_Forward_ForEach |    Forward | 100000 | 496.1 μs | 5.55 μs | 5.19 μs |  1.55 |    0.02 |       - |       - |       - |         - |\n|   DoublyLinkedList_Forward_While |    Forward | 100000 | 306.3 μs | 3.37 μs | 3.15 μs |  0.96 |    0.01 |       - |       - |       - |         - |\n| DoublyLinkedList_Forward_ForEach |    Forward | 100000 | 470.0 μs | 4.44 μs | 3.70 μs |  1.47 |    0.01 |       - |       - |       - |         - |\n|                                  |            |        |          |         |         |       |         |         |         |         |           |\n|         LinkedList_Reverse_While |    Reverse | 100000 | 353.5 μs | 6.03 μs | 5.03 μs |  1.00 |    0.00 |       - |       - |       - |         - |\n|       LinkedList_Reverse_ForEach |    Reverse | 100000 | 934.6 μs | 7.46 μs | 6.23 μs |  2.64 |    0.04 | 41.0156 | 41.0156 | 41.0156 | 400,393 B |\n|   DoublyLinkedList_Reverse_While |    Reverse | 100000 | 356.4 μs | 2.89 μs | 2.70 μs |  1.01 |    0.02 |       - |       - |       - |         - |\n| DoublyLinkedList_Reverse_ForEach |    Reverse | 100000 | 499.3 μs | 6.13 μs | 5.44 μs |  1.42 |    0.03 |       - |       - |       - |         - |\n\n\n## Forward and reverse enumeration\n\n`DoublyLinkedList\u003cT\u003e` does not directly implement `IEnumerable\u003cT\u003e`. Call the properties `Forward` or `Backward` to get an enumerator that goes in the direction you require.\n\n```csharp\nvar list = new DoublyLinkedList\u003cint\u003e(new[] {1, 2, 3, 4});\nforeach (var item in list.Backward)\n\tConsole.Write(item);\n```\noutputs\n```\n4321\n```\n\nThese methods allow the use of LINQ on either direction:\n\n```csharp\nvar list = new DoublyLinkedList\u003cint\u003e(new[] {1, 2, 3, 4});\nConsole.Write(list.Backward.First());\n```\noutputs\n```\n4\n```\n\nAlthough these enumerators are optimized for performance, they perform a bit more method calls and conditions than simply using a `while` loop to go throught the `Node` references. The performance penalty can be seen on the benchmarks above. \n\n```csharp\nvar current = doublyLinkedList.Last;\nwhile (current is object)\n{\n    Console.Write(current.Value);\n    current = current.Previous;\n}\n```\n\nThe enumerators also supports random access by using an indexer. It allows indexing relative to the head or the tail of the list.\n\n```csharp\nvar head = doublyLinkedList.Forward[0];\nvar tail = doublyLinkedList.Backward[0];\n```\n\nPlease note that this `DoublyLinkedList` is not optimized for random access. It will use the shortest path to the item but it will have to step through the list to get there.\n\n## `AddFirst()` and `AddLast()`\n\nThese methods now support the addition of collections of items. These can come from an `IEnumerable\u003cT\u003e`, `IReadOnlyList\u003cT\u003e` or another `DoublyLinkedList\u003cT\u003e`. \n\nWhen the parameter is `IReadOnlyList\u003cT\u003e` or `DoublyLinkedList\u003cT\u003e`, they can be added reversed.\n\n```csharp\nvar list = new DoublyLinkedList\u003cint\u003e(new[] {1, 2, 3, 4});\nvar anotherList = new DoublyLinkedList\u003cint\u003e(new[] {5, 6, 7, 8});\nlist.AddFirst(anotherList, true);\nforeach (var item in list.Forward)\n\tConsole.Write(item);\n```\n\noutputs\n\n```csharp\n87651234\n```\n\n## `AddFirstFrom()` and `AddLastFrom()`\n\nThese methods perform the addition of a `DoublyLinkedList\u003cT\u003e` but moving the nodes into the other `DoublyLinkedList\u003cT\u003e`. No memory allocations and copies of values are performed.\n\nThe `DoublyLinkedList\u003cT\u003e` passed as parameter becomes empty.\n\n## `Append()` \n\nA static method that returns a `DoublyLinkedList\u003cT\u003e` instance with the items of both lists appended. \n\n```csharp\nvar list = DoublyLinkedList.Append(\n\tnew DoublyLinkedList\u003cint\u003e(new[] {1, 2, 3, 4}), \n\tnew DoublyLinkedList\u003cint\u003e(new[] {5, 6, 7, 8}));\nforeach (var item in list.Forward)\n\tConsole.Write(item);\n```\n\noutputs\n\n```\n12345678\n```\n\n## `Clone()` \n\nReturns a shallow clone of the a `DoublyLinkedList\u003cT\u003e`. \n\n```csharp\nvar list = new DoublyLinkedList\u003cint\u003e(new[] {1, 2, 3, 4});\nvar clone = list.Clone();\nforeach (var item in list.Forward)\n\tConsole.Write(item);\n```\n\noutputs\n\n```\n1234\n```\n\n## `Reverse()` \n\nReturns a shallow clone of the a `DoublyLinkedList\u003cT\u003e` with the items in reversed order.\n\n```csharp\nvar list = new DoublyLinkedList\u003cint\u003e(new[] {1, 2, 3, 4});\nvar reversed = list.Reverse();\nforeach (var item in reversed.Forward)\n\tConsole.Write(item);\n```\n\noutputs\n\n```\n4321\n```\n\n## `ReverseInPlace()` \n\n`ReverseInPlace()` reverses the list items in-place. It flips the internal node references with no memory allocations.\n\n```csharp\nvar list = new DoublyLinkedList\u003cint\u003e(new[] {1, 2, 3, 4});\nlist.ReverseInPlace();\nforeach (var item in list.Forward)\n\tConsole.Write(item);\n```\n\nalso outputs\n\n```\n4321\n```\n\n## ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnetfabric%2Fnetfabric.doublylinkedlist","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnetfabric%2Fnetfabric.doublylinkedlist","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnetfabric%2Fnetfabric.doublylinkedlist/lists"}