High‑performance foundational utilities for .NET, providing async/threading primitives, lifetime management tools, Span/Memory polyfills, fast path builders, diagnostics helpers, and essential collection utilities. Designed for correctness, speed, and consistent behavior across modern .NET and .NET Framework.
$ dotnet add package NuExt.SystemNuExt.System is a lightweight, production-ready foundation for everyday .NET development. It brings together high-quality utilities for asynchrony, lifetime management, threading primitives, high‑performance spans/memory helpers, diagnostics, and collection helpers — all with a strong focus on performance, correctness, and developer ergonomics. Use it to reduce boilerplate, standardize common patterns across projects, and keep code fast and clean across modern .NET and .NET Framework.
AsyncLock, ReentrantAsyncLock, AsyncWaitHandleDisposable, AggregateDisposable, AsyncDisposable, AggregateAsyncDisposable, AsyncLifetimeSpan / MemoryExtensions APIs (see below)ValueStringBuilder / ValueListBuilder<T> for zero‑allocation buildingObservableDictionary<TKey, TValue>, ReferenceEqualityComparer (polyfill), ArrayEqualityComparer<T>, and many useful extension helpersPathBuilder (class, IDisposable) and ValuePathBuilder (ref struct) — platform‑independent path buildersPathUtilities — static helpers for common path operationsProcessMonitor, PerformanceMonitor, EnumHelper<T>, TypeExtensions, etc.This package includes polyfills (API backports) for selected Span / MemoryExtensions‑style APIs from newer .NET versions. On modern runtimes, it transparently uses the inbox implementations; on older runtimes, it provides compatible behavior with the same semantics.
What you get (highlights)
Contains, SequenceEqual (+ IEqualityComparer<T>)IndexOf, LastIndexOf (element / sequence)IndexOfAny, LastIndexOfAny, IndexOfAnyExcept, LastIndexOfAnyExceptIndexOfAnyInRange, IndexOfAnyExceptInRange, LastIndexOfAnyInRange, LastIndexOfAnyExceptInRangeStartsWith, EndsWith, Replace (in‑place / copy), Count, CountAnyNotes
System.Threading.AsyncLock, System.Threading.ReentrantAsyncLock, System.Threading.AsyncWaitHandleSystem.ComponentModel.Disposable, AggregateDisposable, AsyncDisposable, AggregateAsyncDisposable, AsyncLifetimeSystem.Collections.ObjectModel.ObservableDictionary<TKey, TValue>System.Collections.Generic.ValueListBuilder<T>System.Collections.Generic.ReferenceEqualityComparer (polyfill)System.Collections.Generic.ArrayEqualityComparer<T>System.Text.ValueStringBuilderSystem.CompatMemoryExtensions (polyfills/backports)System.IO.PathBuilder (class, IDisposable — mutable path builder)System.IO.ValuePathBuilder (ref struct — high‑performance mutable path builder)System.IO.PathUtilities (static common path operations)System.Diagnostics.ProcessMonitor, PerformanceMonitorSystem.EnumHelper<T>, System.FormatUtils, System.HexConvertervar asyncLock = new System.Threading.ReentrantAsyncLock();
var cts = new CancellationTokenSource();
// Synchronous section
asyncLock.Acquire(() =>
{
// do work safely, reentry allowed on the same flow
});
// Asynchronous section
await asyncLock.AcquireAsync(async () =>
{
await DoAsyncWork();
});
// Avoid unintentionally flowing AsyncLocal into CT callbacks:
using (ExecutionContext.SuppressFlow())
{
cts.Token.Register(() => asyncLock.Acquire(() =>
{
// safe callback body
}));
}
var lifetime = new System.AsyncLifetime() { ContinueOnCapturedContext = true };
lifetime.AddDisposable(new FileStream(path, FileMode.Open));
lifetime.AddAsync(async () => await FlushBuffersAsync());
await lifetime.DisposeAsync(); // disposes in the right order, async‑aware
ValueStringBuilderSpan<char> initial = stackalloc char[128];
var sb = new System.Text.ValueStringBuilder(initial);
sb.Append("User: ");
sb.Append(userName);
sb.Append(", Items: ");
sb.Append(itemCount);
string result = sb.ToString(); // minimal allocations
ValueListBuilder<T> and ValueTask.WhenAllpublic class Example
{
public static async Task Main()
{
int failed = 0;
String[] urls = [ "www.adatum.com", "www.cohovineyard.com",
"www.cohowinery.com", "www.northwindtraders.com",
"www.contoso.com" ];
var tasks = new ValueListBuilder<ValueTask>(urls.Length);
foreach (var value in urls)
{
var url = value;
tasks.Append(new ValueTask(Task.Run(() =>
{
var png = new Ping();
try
{
var reply = png.Send(url);
if (reply.Status != IPStatus.Success)
{
Interlocked.Increment(ref failed);
throw new TimeoutException("Unable to reach " + url + ".");
}
}
catch (PingException)
{
Interlocked.Increment(ref failed);
throw;
}
})));
}
ValueTask t = ValueTask.WhenAll(tasks.ToArray());
try
{
await t;
}
catch { }
if (t.IsCompletedSuccessfully)
Console.WriteLine("All ping attempts succeeded.");
else if (t.IsFaulted)
Console.WriteLine("{0} ping attempts failed", failed);
}
}
ValueListBuilder<T> and ValueTask.WhenAll<TResult>public class Example
{
public static async Task Main()
{
int failed = 0;
String[] urls = [ "www.adatum.com", "www.cohovineyard.com",
"www.cohowinery.com", "www.northwindtraders.com",
"www.contoso.com" ];
var tasks = new ValueListBuilder<ValueTask<PingReply>>(urls.Length);
foreach (var value in urls)
{
var url = value;
tasks.Append(new ValueTask<PingReply>(Task.Run(() =>
{
var png = new Ping();
try
{
var reply = png.Send(url);
if (reply.Status != IPStatus.Success)
{
Interlocked.Increment(ref failed);
throw new TimeoutException("Unable to reach " + url + ".");
}
return reply;
}
catch (PingException)
{
Interlocked.Increment(ref failed);
throw;
}
})));
}
try
{
PingReply[] replies = await ValueTask.WhenAll(tasks.ToArray());
Console.WriteLine("{0} ping attempts succeeded:", replies.Length);
for (int i = 0; i < replies.Length; i++)
{
var reply = replies[i];
Console.WriteLine($"Reply from {reply.Address}: bytes={reply.Buffer.Length} time={reply.RoundtripTime}ms TTL={reply.Options?.Ttl} [{urls[i]}]");
}
}
catch (AggregateException)
{
Console.WriteLine("{0} ping attempts failed", failed);
}
}
}
Via NuGet:
dotnet add package NuExt.System
Or via Visual Studio:
Tools -> NuGet Package Manager -> Manage NuGet Packages for Solution....NuExt.System.Some implementations are derived from the .NET Runtime (MIT). See LICENSE and source comments for attributions.
Issues and PRs are welcome. Keep changes minimal and performance-conscious.
MIT. See LICENSE.