Regira.TreeList 6.1.2

dotnet add package Regira.TreeList --version 6.1.2
                    
NuGet\Install-Package Regira.TreeList -Version 6.1.2
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Regira.TreeList" Version="6.1.2" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Regira.TreeList" Version="6.1.2" />
                    
Directory.Packages.props
<PackageReference Include="Regira.TreeList" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Regira.TreeList --version 6.1.2
                    
#r "nuget: Regira.TreeList, 6.1.2"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Regira.TreeList@6.1.2
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Regira.TreeList&version=6.1.2
                    
Install as a Cake Addin
#tool nuget:?package=Regira.TreeList&version=6.1.2
                    
Install as a Cake Tool

Regira TreeList

Regira.TreeList is a generic .NET library for building and navigating hierarchical tree structures. It supports both one-to-many and many-to-many parent-child relationships, provides rich navigation extension methods, and includes built-in protection against circular references.

Core Concepts

Classes & Interfaces

Type Purpose
TreeList<T> Main container — inherits List<TreeNode<T>>
TreeNode<T> A single node holding a value and its children
TreeView<T> Read-only view returning values in depth-first order
ITreeNode<T> Interface for node access (Value, Level, Parent, Children, Root)
InvalidChildException<T> Thrown when adding an ancestor as a child (circular reference)

Node Properties

Property Type Description
Value T The wrapped object
Level int Depth in the tree (0 = root)
Parent TreeNode<T>? Immediate parent, or null for roots
Root TreeNode<T>? Top-most ancestor, or null for a root node
Children ICollection<TreeNode<T>> Direct children

Root exposes the top-most ancestor directly; the GetRoot() extension computes it by walking the Parent chain when you hold a bare TreeNode<T>.

Installation

<PackageReference Include="Regira.TreeList" Version="6.*" />

Building a Tree

From a flat collection with a parent selector

var people = new[]
{
    new Person { Id = 1, Name = "Alice", ParentId = null },
    new Person { Id = 2, Name = "Bob",   ParentId = 1 },
    new Person { Id = 3, Name = "Carol", ParentId = 1 },
};

// Single-parent selector
var tree = people.ToTreeList(p => people.FirstOrDefault(x => x.Id == p.ParentId));

Console.WriteLine(tree.Roots.Length);              // 1  (Alice)
Console.WriteLine(tree.Roots[0].Children.Count);   // 2  (Bob, Carol)

From roots with a children selector (best performance)

var roots = people.Where(p => p.ParentId == null);

var tree = people.ToTreeList(
    roots,
    node => people.Where(p => p.ParentId == node.Value.Id));

Manual construction

var tree = new TreeList<string>();
var root = tree.AddValue("root");
var child = tree.AddValue("child", root);
child!.AddChild("grandchild");

Once the tree is built every node exposes navigation extension methods:

var node = tree.First(n => n.Value.Name == "Bob");

// Single-node navigation
var root      = node.GetRoot();         // Alice
var ancestors = node.GetAncestors();    // [Alice]
var children  = node.GetChildren();     // direct children of Bob
var offspring = node.GetOffspring();    // all descendants of Bob (recursive)
var siblings  = node.GetBrothers();     // Carol (same parent, excluding self)
var uncles    = node.GetUncles();       // children of Alice's siblings
var nephews   = node.GetNephews();      // children of uncles

Extension methods also work on collections of nodes:

IEnumerable<TreeNode<Person>> subset = tree.Where(n => n.Level == 1);

var roots     = subset.GetRoots();      // root nodes reachable from subset
var ancestors = subset.GetAncestors();  // all ancestors (distinct)
var parents   = subset.GetParents();    // distinct parent nodes
var leaves    = tree.GetBottom();       // nodes with no children
var offspring = subset.GetOffspring();  // all descendants
var withSelf  = subset.WithOffspring(); // self + all descendants

Ordering & Views

// Depth-first traversal (default)
var ordered = tree.OrderByHierarchy();

// Depth-first with a custom sort key per level
var orderedByName = tree.OrderByHierarchy(n => n.Value.Name);

// Read-only view — values in depth-first order
TreeView<Person> view = tree.ToTreeView();

Reversing a Tree

ReverseTree inverts all parent-child relationships.
Leaf nodes become roots; the original root becomes a leaf.

var reversed = tree.ReverseTree();

Error Handling

By default the tree throws InvalidChildException<T> when a circular reference is detected.
This behaviour can be configured:

var tree = new TreeList<Person>(new TreeList<Person>.TreeOptions
{
    EnableAutoCheck = true,   // validate before adding (default: true)
    ThrowOnError    = false   // return null instead of throwing (default: true)
});

var invalidNode = tree.AddValue(ancestor, descendantNode); // returns null

Overview

  1. Index — Overview and basic usage
  2. Examples — FamilyTree (one-to-many) & CookbookTree (many-to-many)

License

Apache License 2.0 — this package contains no license validation and no runtime limits. See LICENSE. A few companion packages are commercially licensed with a free tier; see the licensing overview.

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (2)

Showing the top 2 NuGet packages that depend on Regira.TreeList:

Package Downloads
Regira.System.Projects

Project file and solution structure utilities for Regira system tools.

Regira.Office.Word.Spire

Word document processing using FreeSpire.Doc for Regira Office.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
6.1.2 79 8/16/2026
6.1.1 109 8/12/2026
6.1.0 135 8/10/2026