ktsu.Semantics.Paths
3.2.0
Prefix Reserved
dotnet add package ktsu.Semantics.Paths --version 3.2.0
NuGet\Install-Package ktsu.Semantics.Paths -Version 3.2.0
<PackageReference Include="ktsu.Semantics.Paths" Version="3.2.0" />
<PackageVersion Include="ktsu.Semantics.Paths" Version="3.2.0" />
<PackageReference Include="ktsu.Semantics.Paths" />
paket add ktsu.Semantics.Paths --version 3.2.0
#r "nuget: ktsu.Semantics.Paths, 3.2.0"
#:package ktsu.Semantics.Paths@3.2.0
#addin nuget:?package=ktsu.Semantics.Paths&version=3.2.0
#tool nuget:?package=ktsu.Semantics.Paths&version=3.2.0
ktsu.Semantics.Paths
Polymorphic, strongly-typed file system path types that keep files, directories, absolute, and relative paths distinct at compile time.
ktsu.Semantics.Paths is one package in the ktsu.Semantics family. It builds on ktsu.Semantics.Strings, which supplies the underlying SemanticString<T> machinery.
Introduction
ktsu.Semantics.Paths models a file system path as a type, not a bare string. The type encodes two independent facts: whether the path names a file or a directory, and whether it is absolute or relative. That gives concrete types like AbsoluteFilePath, RelativeDirectoryPath, and orientation-agnostic FilePath / DirectoryPath, all implementing a shared IPath interface hierarchy. You can hold mixed paths in a List<IPath> and filter by capability with OfType<IFilePath>().
Paths are canonicalized on creation (separators normalized, trailing separators trimmed), convert implicitly to string so they drop into any System.IO API, and compose with a / operator that returns the correctly-typed result.
Features
- Interface hierarchy:
IPathwithIFilePath,IDirectoryPath,IAbsolutePath,IRelativePath, and the four combinations (IAbsoluteFilePath,IAbsoluteDirectoryPath,IRelativeFilePath,IRelativeDirectoryPath). - Eight concrete path types:
AbsolutePath,RelativePath,FilePath,DirectoryPath,AbsoluteFilePath,AbsoluteDirectoryPath,RelativeFilePath,RelativeDirectoryPath. - Path decomposition:
FileName,FileExtension,FullFileExtension(for.tar.gz),DirectoryPath,FileNameWithoutExtension, plus theFileName/FileExtension/DirectoryNameprimitive value types. - Composition with
/:directory / relativePath,directory / FileName, and similar, each returning the right result type. - Absolute/relative conversions:
AsAbsolute(),AsAbsolute(baseDirectory), andAsRelative(baseDirectory). - Directory navigation:
Parent,Depth,IsRoot,GetAncestors(),IsChildOf,IsParentOf, and strongly-typedGetContents()enumeration. - Filesystem checks:
Exists,IsFile,IsDirectory. - Validation and canonicalization inherited from the semantic string framework, driven by path attributes such as
[IsAbsolutePath],[IsFileName], and[IsFileExtension].
Installation
Package Manager Console
Install-Package ktsu.Semantics.Paths
.NET CLI
dotnet add package ktsu.Semantics.Paths
Package Reference
<PackageReference Include="ktsu.Semantics.Paths" Version="x.y.z" />
Usage Examples
Basic Example
using ktsu.Semantics.Paths;
// Build paths with the typed factory, then compose with the '/' operator
AbsoluteDirectoryPath projectDir = AbsoluteDirectoryPath.Create(@"C:\repos\app");
RelativeFilePath rel = RelativeFilePath.Create(@"src\Program.cs");
AbsoluteFilePath source = projectDir / rel; // C:\repos\app\src\Program.cs
FileName name = source.FileName; // Program.cs
FileExtension ext = source.FileExtension; // .cs
AbsoluteDirectoryPath dir = source.AbsoluteDirectoryPath;
if (source.Exists)
{
// implicit conversion to string drops straight into System.IO
string text = System.IO.File.ReadAllText(source);
}
Absolute and relative conversions
using ktsu.Semantics.Paths;
AbsoluteDirectoryPath root = AbsoluteDirectoryPath.Create(@"C:\data");
AbsoluteFilePath file = AbsoluteFilePath.Create(@"C:\data\logs\app.log");
RelativeFilePath relative = file.AsRelative(root); // logs\app.log
AbsoluteFilePath backAgain = relative.AsAbsolute(root); // C:\data\logs\app.log
AbsoluteFilePath renamed = file.ChangeExtension(FileExtension.Create(".bak"));
bool nested = file.IsChildOf(root); // true
AsAbsolute() with no argument resolves a relative path against the current working directory. The baseDirectory overload of AsAbsolute exists on the relative path types only.
Polymorphic collections and typed enumeration
using ktsu.Semantics.Paths;
List<IPath> all =
[
AbsoluteFilePath.Create(@"C:\data.txt"),
RelativeDirectoryPath.Create(@"logs\app"),
FilePath.Create(@"document.pdf"),
];
List<IFilePath> files = all.OfType<IFilePath>().ToList();
List<IAbsolutePath> absolutes = all.OfType<IAbsolutePath>().ToList();
// GetContents() yields correctly-typed children
AbsoluteDirectoryPath project = AbsoluteDirectoryPath.Create(@"C:\project");
foreach (IPath entry in project.GetContents())
{
switch (entry)
{
case AbsoluteFilePath f:
Console.WriteLine($"file: {f.FileName} ({f.FileExtension})");
break;
case AbsoluteDirectoryPath d:
Console.WriteLine($"dir: {d.Name} at depth {d.Depth}");
break;
}
}
GetContents() returns an empty sequence rather than throwing when the directory is missing or access is denied.
API Reference
Interface hierarchy
| Interface | Extends | Notable member |
|---|---|---|
IPath |
(none) | marker |
IFilePath |
IPath |
AbsoluteFilePath AsAbsolute() |
IDirectoryPath |
IPath |
AsAbsolute(), IEnumerable<IPath> GetContents() |
IAbsolutePath |
IPath |
AbsolutePath AsAbsolute() |
IRelativePath |
IPath |
AbsolutePath AsAbsolute() |
IAbsoluteFilePath |
IFilePath, IAbsolutePath |
typed AsAbsolute() |
IAbsoluteDirectoryPath |
IDirectoryPath, IAbsolutePath |
typed AsAbsolute() |
IRelativeFilePath |
IFilePath, IRelativePath |
typed AsAbsolute() |
IRelativeDirectoryPath |
IDirectoryPath, IRelativePath |
typed AsAbsolute() |
Concrete types and creation
All concrete types are sealed records created through the inherited static factory Create(...) (accepting string, char[], or ReadOnlySpan<char>). Create throws ArgumentException on invalid input and ArgumentNullException on null.
| Type | Kind | Interface |
|---|---|---|
AbsolutePath |
untyped absolute | IAbsolutePath |
RelativePath |
untyped relative | IRelativePath |
FilePath |
orientation-agnostic file | IFilePath |
DirectoryPath |
orientation-agnostic directory | IDirectoryPath |
AbsoluteFilePath |
absolute file | IAbsoluteFilePath |
AbsoluteDirectoryPath |
absolute directory | IAbsoluteDirectoryPath |
RelativeFilePath |
relative file | IRelativeFilePath |
RelativeDirectoryPath |
relative directory | IRelativeDirectoryPath |
The primitive component types FileName, FileExtension, and DirectoryName are semantic strings in their own right.
Common members
| Name | Type | Description |
|---|---|---|
Exists |
bool |
True if the path is an existing file or directory. |
IsFile / IsDirectory |
bool |
Filesystem-backed checks. |
FileName |
FileName |
Filename portion (file paths). |
FileExtension / FullFileExtension |
FileExtension |
Last extension / everything from the first dot. |
DirectoryPath |
DirectoryPath |
Directory portion of a file path. |
Parent / Name / Depth / IsRoot |
directory members | Directory navigation. |
AsAbsolute() |
typed absolute path | Resolve against the current working directory. |
AsAbsolute(AbsoluteDirectoryPath) |
typed absolute path | Resolve a relative path against a base (relative types only). |
AsRelative(AbsoluteDirectoryPath) |
typed relative path | Make relative to a base directory. |
GetContents() |
IEnumerable<IPath> |
Strongly-typed directory children. |
operator / |
typed result | Combine a directory with a relative path, FileName, or DirectoryName. |
Contributing
Contributions are welcome! Feel free to open issues or submit pull requests.
License
This project is licensed under the MIT License. See the LICENSE.md file for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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 is compatible. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 is compatible. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- ktsu.Semantics.Strings (>= 3.2.0)
- System.Memory (>= 4.6.3)
- System.Threading.Tasks.Extensions (>= 4.6.3)
-
.NETStandard 2.1
- ktsu.Semantics.Strings (>= 3.2.0)
-
net10.0
- ktsu.Semantics.Strings (>= 3.2.0)
-
net8.0
- ktsu.Semantics.Strings (>= 3.2.0)
-
net9.0
- ktsu.Semantics.Strings (>= 3.2.0)
NuGet packages (20)
Showing the top 5 NuGet packages that depend on ktsu.Semantics.Paths:
| Package | Downloads |
|---|---|
|
ktsu.AppDataStorage
A .NET library for persistent application data storage using JSON serialization. Provides a simple inherit-and-use pattern with automatic file management, thread-safe operations, debounced saves, backup recovery, and singleton access. Stores data in the user's app data folder with support for custom subdirectories and file names. |
|
|
ktsu.ImGui.Popups
A professional library for modal dialogs and popup components in ImGui.NET, providing message boxes, input prompts with validation (string, int, float), searchable selection lists with type-safe generics, and an advanced filesystem browser with open/save modes, directory navigation, and pattern filtering support. |
|
|
ktsu.SingleAppInstance
A lightweight .NET library that ensures only one instance of an application is running at a time. Uses a JSON-serialized PID file with multi-attribute process verification (PID, name, start time, executable path) for accurate instance detection, built-in race condition handling for simultaneous startups, and backward compatibility with legacy PID formats. Supports .NET 10.0 through .NET Standard 2.0. |
|
|
ktsu.ImGui.App
A comprehensive .NET library that provides complete application scaffolding for Dear ImGui applications, featuring window management, DPI-aware rendering, precision PID-controlled frame limiting with comprehensive auto-tuning, advanced font handling with Unicode/emoji support, texture management, and debug tooling. Built on Silk.NET for cross-platform OpenGL support and Hexa.NET.ImGui for modern Dear ImGui bindings. |
|
|
ktsu.ImGui.Widgets
A comprehensive library of custom widgets and UI components for ImGui.NET, featuring radial progress bars with countdown/count-up timers, tabbed interfaces with drag-and-drop support, type-safe combo boxes, resizable divider containers, powerful search boxes with fuzzy matching, icons with event handling, flexible grid layouts, and scoped utilities for IDs and disabling elements. |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 3.2.0 | 0 | 8/27/2026 |
| 3.1.4 | 153 | 8/25/2026 |
| 3.1.3 | 574 | 8/24/2026 |
| 3.1.2 | 671 | 8/21/2026 |
| 3.1.1 | 1,165 | 8/19/2026 |
| 3.1.0 | 445 | 8/19/2026 |
| 3.0.1 | 717 | 8/18/2026 |
| 3.0.0 | 1,085 | 8/15/2026 |
| 2.9.14 | 1,006 | 8/14/2026 |
| 2.9.13 | 113 | 8/14/2026 |
| 2.9.12 | 101 | 8/14/2026 |
| 2.9.11 | 113 | 8/14/2026 |
| 2.9.10 | 274 | 8/14/2026 |
| 2.9.9 | 104 | 8/14/2026 |
| 2.9.8 | 96 | 8/14/2026 |
| 2.9.7 | 109 | 8/14/2026 |
| 2.9.6 | 117 | 8/14/2026 |
| 2.9.5 | 99 | 8/14/2026 |
| 2.9.4 | 112 | 8/14/2026 |
| 2.9.3 | 944 | 8/7/2026 |
## v3.2.0 (minor)
Changes since v3.1.0:
- test: cover the diagnostic sites and location fallbacks this PR touched [patch] ([@Claude](https://github.com/Claude))
- refactor: clear the Sonar findings the wider analyzer reach exposed [patch] ([@Claude](https://github.com/Claude))
- test: make the path tests run on Linux [patch] ([@Claude](https://github.com/Claude))
- docs: make the local Sonar reproduction reach every project [patch] ([@Claude](https://github.com/Claude))
- build: silence RS2002 for the generator project [patch] ([@Claude](https://github.com/Claude))
- fix: point SEM001 and SEM003 at the metadata they are complaining about [patch] ([@Claude](https://github.com/Claude))
- refactor: pin the generated line terminator, drop the rewrite pass [minor] ([@Claude](https://github.com/Claude))
- refactor: emit through ktsu.CodeBlocker.Templates [minor] ([@Claude](https://github.com/Claude))
- refactor: filter explicitly instead of inside the loop body [patch] ([@Claude](https://github.com/Claude))
- fix: satisfy the IDE style rules in the new test files [patch] ([@Claude](https://github.com/Claude))
- refactor: shape the generator infrastructure for extraction [minor] ([@Claude](https://github.com/Claude))
- ci: make the SonarQube quality gate opt in [patch] ([@matt-edmondson](https://github.com/matt-edmondson))
- ci: adopt the unified dotnet workflow [patch] ([@matt-edmondson](https://github.com/matt-edmondson))