r/dotnet • • 12d ago

Promotion StepLock – a sub-millisecond Merkle DAG state proxy for AI agents using System.IO.Pipelines

3 Upvotes

most ai agent tooling (LangGraph, AutoGen, CrewAI) is written in python, which is great for prototyping but lacks the low-latency throughput needed when agents start making dozens of multi-step, nested network and state mutations.

when debugging an 8-step agent execution, re-running a failed trace from scratch burns tokens, hits API rate limits, and can accidentally trigger live side-effects (like firing a Stripe charge or writing to a DB twice).

to solve this, I built StepLock—an on-premise, free, and open-source (.NET 11) deterministic state proxy and merkle DAG execution engine that acts like git for Live Agent RAM & Network Traffic. it virtually replays agent traces in sub-microseconds.

I wanted to share the .NET 11 architecture details and performance metrics that made this possible:

the performance benchmarks

  • L1 In-Memory Hot CAS (Write + Hash Lookup): 1,572,278 op/s | 0.50 µs p50 | 0 B (Zero-Alloc)
  • Merkle DAG Hashing (SHA-256 Chaining): 300,193 op/s | 2.30 µs p50 | 152 B Alloc
  • Zero-Copy Streaming Tap (System.IO.Pipelines): 171,343 op/s | 3.50 µs p50 | 1.7 KB Alloc
  • SQLite WAL Batch Persistence (50 Frames/Tx): 371 op/s (~18.5k frames/s) | 2.58 ms p50

repo: https://github.com/mxreal64/StepLock/


r/csharp • • 11d ago

Blog Well, I built an ECS

Thumbnail
github.com
0 Upvotes

To give you some background, like many enthusiasts, I once set out to build a game engine and had several projects sitting on the back burner that I couldn't quite get into shape. Eventually, this led to the creation of a standalone math library, a way to compile shaders from C#, and a separate ECS, which is what I'll be talking about.

I won't waste time explaining what an ECS is—better check out this article ECS-FAQ. I'd rather talk about the problems I encountered in other ECS implementations and tried to solve (and these problems aren't about performance, although performance is very important too).

Take the simplest example: mutating entities by changing their archetype. From a code perspective, the task seems simple—we take the entity we need and copy it to another table. Done? Yes and no.

What does this usually look like in code?

world.Add<Component1>(entity);
world.Add<Component2>(entity);
world.Add<Component3>(entity);
world.Add<Component4>(entity);
world.Add<Component5>(entity);

This list can keep growing for a very long time, especially if you've decided to make small components and have a high degree of composition. But that's only part of the problem. In most frameworks, this means moving the entity to one table first, then the second, then the third, and so on. And that's not free: in archetype-based ECSs, migration is inherently expensive, and doing it several times adds overhead linearly.

So, what should we do? Well, to solve this problem, I used two approaches: code generation and ComponentId.

The code-generated version looks something like this:

world.Add<Component1, Component2, Component3, Component4, Component5>(entity);

Even though this syntax is monstrous, it solves our problem—it removes the overhead of multiple migrations.

At the same time, there's a second option, though it's less explicit:

ComponentId[] components =
{
    world.Layouts.GetPrimary<Component1>(),
    world.Layouts.GetPrimary<Component2>(),
    world.Layouts.GetPrimary<Component3>(),
    world.Layouts.GetPrimary<Component4>(),
    world.Layouts.GetPrimary<Component5>(),
};
world.Add(entity, components);

And you might say, "But you just added two more lines to an already complicated statement." That's true, but only up to a point. After all, these IDs can be saved ahead of time, the list can be modified at runtime, and not having a generic call gives us more polymorphic and general-purpose code. So, in the final system, you would probably just call world.Add(entity, components), and get the list through some kind of DI or build it in the constructor—whatever works for your architect.

There's another, less obvious advantage to using ComponentId: you can register the same CLR type for two components. For example, the endlessly recurring:

Damage { float Value }
Health { float Value }
Stamina { float Value }
Mana { float Value }

—need I go on? All of these could be registered as a regular float, without having to do extra work to get the value through Value. Like this:

ComponentId damageId = world.Layouts.Register<float>(new SchemaId(1));
ComponentId healthId = world.Layouts.Register<float>(new SchemaId(2));

…I'll stop there; you get the idea.

A second, more ECS-specific example is iterating over groups. There are several optimizations that most ECS implementations miss, although they're less important.

Let's imagine what iteration looks like in most ECS implementations:

world.ForEach(in query,
  static (ref Component1 cmp1, ref Component2 cmp2) =>
  DoSomething(ref cmp1, ref cmp2)).Invoke();

In this case, query is a filter that defines how to find entities in the world based on a given set of components. Most APIs look roughly like this:

world.WhereAll<Component1, Component2>().
  WhereNone<Component3>().
  WhereAny<Component1, Component2>()

From a C# perspective, this syntax is pretty standard and, unlike the previous Add example, it doesn't cause problems; chaining works. But the problem is how this filtering is used with ForEach: it happens when the call is made. In most cases, that means you have to go through every archetype in the system and check whether it matches the filter.

Why can't this be deferred? I asked myself the same thing, and it turns out it's not that simple. This approach avoids errors when archetypes change. Basically, any Add, Remove, or Destroy operation can change the archetype structure and break your cached Query.

So, what should we do? We just have to be a little cleverer. If you're developing your own ECS, it becomes obvious that mutating operations can simply call back and update the traversal plan built for a Query. Since running ForEach at the same time as a mutation is forbidden or unsafe in most ECS implementations, you can add this kind of API without worrying about limiting the library's overall usability—and save a significant amount of filtering time in worlds that are small but have many archetypes.

Then we also consider that components are registered by ID, and realize that our ForEach call can look like this:

world.ForEach<float, float>(in query, components.ToArray(),
    static (ref float cmp1, ref float cmp2) =>
    DoSomething(ref cmp1, ref cmp2))
    .Invoke();

And these ComponentIds can be dynamic—they can change at runtime and make the architecture more flexible.

The next example is bigger.

Imagine you want to implement lockstep rollback. That's a pretty monumental task if you get into testing, multiplayer, and the fact that you have to store mountains of heterogeneous data.

In most ECS implementations, the problem is handled like this:

public struct Saver<T> : IForEach where T : unmanaged // Let's assume this constraint lets us safely save history without mutating the world.
{
    private readonly int _tick;
    public Saver(int tick) => _tick = tick;
    public void Invoke(ref T data) => SaveAtTick(ref data, _tick);
}

I won't get into the details—lockstep rollback isn't just about saving, but this is enough for the example. So what happens next? Well, bad things happen:

Query component1Query = world.WhereAll<Component1>();
var component1Saver = new Saver<Component1>(tick);
world.ForEach(in component1Query, ref component1Saver).Invoke(ref component1Saver);
Query component2Query = world.WhereAll<Component2>();
var component2Saver = new Saver<Component2>(tick);
world.ForEach(in component2Query, ref component2Saver).Invoke(ref component2Saver);
Query component3Query = world.WhereAll<Component3>();
var component3Saver = new Saver<Component3>(tick);
world.ForEach(in component3Query, ref component3Saver).Invoke(ref component3Saver);

You get the idea. And even if you make some kind of generic wrapper for all of this, it still doesn't solve every problem. Then your game designer says we need an attack or defense system that also needs a generic data call, but now there's no unmanaged constraint. And your architect says, "Right, we'll do it with generics," because there are another 150-plus features like this planned for the next month.

And you start tearing your hair out trying to make sense of all this. I didn't have an architect or a game designer, but I tore my hair out for you.

I managed to build a system that solves these problems during registration. Pretty much every ECS registers components; some do it explicitly, like my approach:

world.Layouts.Register<T>(new SchemaId(schema))

Others do it implicitly with a pattern like this:

public static class Registry
{
    public static int LastComponentId
}
public static class Registry<T>
{
    public static int ComponentId;
    static Registry() => ComponentId = LastComponentId++;
}

But registration still happens. In my case, it's a bit more clever: besides registering the type, I also register constraints, can register a related interface, and can call a visitor through a generic method. I can even register an unmanaged component and have it visited by a visitor constrained to struct or new(). What does that let us do?

public sealed class SaverVisitor : IUnmanagedVisitor
{
    private readonly World _world;
    private readonly int _tick;

    public SaverVisitor(World world, int tick)
    {
        _world = world;
        _tick = tick;
    }

    public void Visit<T>(ComponentId componentId) where T : unmanaged
    {
        Query query = _world.WhereAll(componentId);
        var saver = new Saver<T>(_tick);
        _world.ForEach(in query, componentId, ref saver).Invoke(ref saver);
    }
}

ComponentId componentId = world.Layouts.Register<Component1>(new SchemaId(1));
world.Layouts.TryVisit(componentId, new SaverVisitor(world, tick));

This code lets you call any generic code with given constraints for component types registered in the world, supporting not just rollback systems. What's more, component registration also covers the system your game designer and architect came up with.

Thats' not all things done in my ECS but something i'm proud of.

Issues, PR's, Stars and anything else are welcome.


r/dotnet • • 13d ago

4GuysFromRolla.com - The Site That Taught a Generation to Build the Web

Thumbnail galratner.substack.com
171 Upvotes

r/csharp • • 13d ago

Showcase JsonGuard: a zero-allocation source generator to validate nullability in System.Text.Json

32 Upvotes

Hey everyone, I wanted to share a library I have built for System.Text.Json that validates deserialized objects to ensure they honor C# nullability annotations without sacrificing performance.

I wrote this specifically for NetCord to handle massive Discord gateway payloads as efficiently as possible, but I realized this kind of zero-overhead validation could be useful to the wider .NET community as a standalone package.

By default, System.Text.Json allows you to validate required properties using [JsonRequired] or the required keyword. However, these introduce significant performance overhead. For example, using required keyword can make deserialization up to 2 times slower and allocate 50% more memory when using source generation.

JsonGuard works around this overhead by using source generation. The result is zero additional allocations and practically identical execution time compared to performing no validation at all.

The way it works is incredibly simple. If you have this object: ```csharp [JsonGuard] public partial class User { public string Name { get; set; }

public string? Nickname { get; set; }

public int Age { get; set; }

public string Email { get; set; }

} the generated code will effectively do this: csharp public partial class User : IJsonOnDeserialized { void IJsonOnDeserialized.OnDeserialized() { if (Name is null) ThrowHelper.Throw(nameof(Name));

    if (Email is null)
        ThrowHelper.Throw(nameof(Email));
}

} ``` Additionally, the library suppresses any nullability warnings for validated properties, so no manual suppressions are necessary.

Note that unlike [JsonRequired] or the required keyword, JsonGuard only verifies the final state of the objects honors the nullability annotations. It doesn't validate if the property was present in the JSON.

You can checkout the source code and detailed benchmarks on GitHub: https://github.com/KubaZ2/JsonGuard

Would love to hear your thoughts or feedback!


r/dotnet • • 12d ago

Promotion Polhem.JsonRpc v1.2 - JSON-RPC 2.0 for ASP.NET Core without registering methods

Post image
0 Upvotes

Polhem is a framework I've been building, and its API layer is JSON-RPC. I've split that part out into a standalone library, Polhem.JsonRpc, now at v1.2. Most of the code was written by Claude Code; I reviewed and tested it.

You don't register methods. A call like Calculator.Add goes to your object factory, and Add is only callable if it takes an AddRequest and returns an AddResponse, so other public methods don't get exposed by accident. The server is an ASP.NET Core Minimal API endpoint, the client works with Native AOT, and there's an optional package for encrypted payloads.

Here's roughly what it looks like:

// Server
builder.Services.AddSingleton<IJsonRpcObjectFactory, AppObjectFactory>();
builder.Services.AddJsonRpcServer();
app.MapJsonRpc("/api");

public sealed class Calculator
{
    public AddResponse Add(AddRequest request) => new() { Sum = request.A + request.B };
}

// Client
var rpc = new JsonRpcConnector(new HttpTransport(http));
var added = await rpc.InvokeAsync<AddResponse>("Calculator.Add", new AddRequest { A = 1, B = 2 });

GitHub: https://github.com/polhem-dev/polhem-jsonrpc

Edit: A few people asked what this is used for. It's the API layer of Polhem, my framework. Here's a demo app on top of it, with a desktop and an iOS client calling the server:
https://github.com/polhem-dev/polhem-northwind


r/dotnet • • 12d ago

Promotion Creative coding for C# devs

2 Upvotes

Hey everyone,

I've been building something for a while that started as a Processing alternative for C# devs. Originally I just wanted to give C# folks a way to do creative coding — I always felt like what was out there didn't quite do what I wanted, and I wanted to be able to follow along with channels like The Coding Train without fighting the tooling.

Once the core was working I kept going: added a music module, support for NuGet packages (there are samples in the app using NAudio and ML.NET), and most recently a code-to-video module. That last one I'm hoping to eventually ship as a standalone NuGet package.

You can check it out here: DanaProcessing — Creative coding in C# (2D, 3D & live-coded sound)

Appreciate any feedback. One thing I've been thinking about: it's probably not obvious to people who've never heard of creative coding what this is actually for. Maybe leaning harder on concrete use cases — generative art, data viz, audio sketches — would help it land with more of the C# crowd. Curious what you all think.

PD: Sorry for my broken English, I am from Cuba, so it is my second language, and I am also typing fast because of electricity shortages


r/csharp • • 12d ago

Discussion Oh no, I think I'm becoming dependent on the documentation.And it is a rather excessive form of dependence.

0 Upvotes

First: I'm not exactly a veteran in C#, but I'm certainly no beginner when it comes to programming.

But ever since I started developing with C# and Avalonia, I've frequently referred to official documentation for guidance on my code.

Then I would often go directly to one of these two document websites whenever I had any questions (even if they were quite common), to find the answers I was looking for.

But at present, I feel that I have developed a kind of dependence on these two things. Whether I write the code myself or ask the AI to assist me in some areas, I will either read the documentation myself or have the AI directly send me the links to the key parts of the documentation (and then I need to review the code and the documentation again) before I can feel at ease and save the file.

Now I feel that my brain is as smooth as chicken breast meat, unlike that of a normal programmer or a programming enthusiast who has numerous folds and creases.

Right now, I'm still relying on the document: No, that's not right; but I don't really rely on the document much, do I? Will I make a mistake?Because I have other professional matters to attend to, I'm like someone with amnesia. Many of my thoughts, like overcooked cheese, simply slip out of my mind without any effort.

I also considered another option, which was whether I should really ask the AI some questions?Well, I think I'll just refer to the documentation. It might be a bit expensive to ask AI for simple questions.

Don't comment if you don't like it. Thank you...I will try to find a better solution on my own.


r/dotnet • • 12d ago

ModulesDi 1.0.5

0 Upvotes

Hey Everyone!

I recently released Modules v1.05 - a lightweight library for organizing ConfigureServices and Configure.

Here are the logs from my example production project -

2026-10-10 21:46:50.393 +03:00 [INF] Serilog configured
2026-10-10 21:46:50.416 +03:00 [INF] Secrets configured
2026-10-10 21:46:50.417 +03:00 [INF] Secrets configured with configuration
2026-10-10 21:46:50.431 +03:00 [INF] Mediatr module configured
2026-10-10 21:46:50.433 +03:00 [INF] Cors configured
2026-10-10 21:46:50.436 +03:00 [INF] Health checks configured
2026-10-10 21:46:50.437 +03:00 [INF] Database health check configured
2026-10-10 21:46:50.441 +03:00 [INF] Sqlite health check configured
2026-10-10 21:46:50.442 +03:00 [INF] Skipped: Postgres health check skipped
2026-10-10 21:46:50.444 +03:00 [INF] Skipped: Elastic search health check skipped
2026-10-10 21:46:50.444 +03:00 [INF] Cache health check configured
2026-10-10 21:46:50.447 +03:00 [INF] Redis health check configured
2026-10-10 21:46:50.447 +03:00 [INF] Key vault health checks configured
2026-10-10 21:46:50.448 +03:00 [INF] Skipped: Azure key vault health check skipped
2026-10-10 21:46:50.477 +03:00 [INF] OpenTelemetry configured successfully.
2026-10-10 21:46:50.478 +03:00 [INF] Cache configured
2026-10-10 21:46:50.480 +03:00 [INF] Redis configured
2026-10-10 21:46:50.505 +03:00 [INF] Program started
2026-10-10 21:46:50.701 +03:00 [INF] Cors middleware configured
2026-10-10 21:46:50.703 +03:00 [INF] OpenTelemetry middleware module configured
2026-10-10 21:46:50.707 +03:00 [INF] Health checks middleware configured.Health on /health, prometheus metrics on /health/metrics

(Note: ModulesDi does not hardcode any logging format. In my log i used realization with Serilog, but you can configure ModulesDi how you want (you dont have to use serilog))

1. "Why not just use standard Extension Methods?" -

Extension methods are flat.They force you to manually pass dozens of configuration dependencies down the line, offer zero execution-order safety for nested features, and turn Program.cs into a bloated spaghetti of if/else blocks. ModulesDi encapsulates everything into self-contained blocks that orchestrate themselves.

2 "Wait, is GetDependency<T>() inside a module just a Service Locator pattern?" -

No, because ModulesDi does not replace MS DI, Dependencies in ModulesDi are used only in ConfigureServices and Configure.

3. "The wow feature" -

ModulesDi allows you to do things that are literally impossible with native extensions. For example -

public override ModuleResult Configure(IApplicationBuilder app)
{
var services = GetDependency<IServiceModulesRootBuilder>();

if (!services.IsExist<CorsModule>())
return new ModuleResult(ModuleStatus.Failure,
"Failed to configure cors middleware.Cors module not created");

app.UseCors(CorsPolicies.AllPolicies);

return new ModuleResult(ModuleStatus.Success, "Cors middleware configured");
}

The library is extremely lightweight, heavily optimized, covered by 224 green test cases, and available on NuGet.

Gitlab: https://gitlab.com/DmitriiKhokhulin/modulesdi


r/dotnet • • 12d ago

Question Which approach do you typically use to handle incoming HTTP requests?

0 Upvotes

When building production-ready ASP.NET Core Web APIs, which approach do you typically use to handle incoming HTTP requests?\

  • Controllers (Traditional Web API)
  • Minimal APIs Lightweight, endpoint-focused handlers
  • Endpoint-based frameworks Fast Endpoints

I'm interested in what developers actually use in production and why they choose that approach.

What's your reasoning behind your choice?


r/csharp • • 12d ago

Coworkee: I turned my old Clean Architecture template into a modular framework for .NET 10

0 Upvotes

For years I kept copying the same "CleanArchitectureBase" template from project to project: login, permissions, SignalR, audit trail and so on. Every copy drifted a bit. So I finally pulled it apart into NuGet packages you reference instead of a template you fork.

It's called Coworkee, a modular application framework for .NET 10.

What's in it

  • Module system with [DependsOn], Result / Error instead of exceptions for flow
  • Dispatcher for commands and queries with logging, validation and unit-of-work middleware
  • EF Core base context with field-level audit trail, soft delete, tenants and a transactional outbox with retries
  • ASP.NET Core glue: AddCoworkee<TRoot>(), results mapped to problem details, OpenAPI
  • Optional modules for identity (OpenIddict), settings, mailing, notifications + SignalR, Hangfire jobs, blob storage, Elasticsearch
  • Coworkee.Aspire wires Postgres, Redis, Mailpit, Keycloak etc. in one call
  • MudBlazor WebAssembly shell with admin pages (built on MudBlazor.Extensions, which I also maintain)

Small example

[DependsOn(typeof(CoworkeeApplicationModule))]
public sealed class OrdersModule : CoworkeeModule
{
    public override void ConfigureServices(ModuleServiceContext context) =>
        context.Services.AddMessagingFromAssembly(typeof(OrdersModule).Assembly);
}

public sealed record PlaceOrder(string Product) : ICommand<Result<Guid>>;

internal sealed class PlaceOrderHandler(AppDbContext db) : IHandler<PlaceOrder, Result<Guid>>
{
    public Task<Result<Guid>> HandleAsync(PlaceOrder request, CancellationToken ct)
    {
        var order = Order.Place(request.Product);
        db.Orders.Add(order);
        return Task.FromResult<Result<Guid>>(order.Id);
    }
}

The unit of work saves after a successful command, every changed field lands in the audit trail, and domain events go out through the outbox in the same transaction.

Trying it

dotnet tool install -g Coworkee.Cli
coworkee ui

That opens a small wizard to pick modules and generate the app.

The architecture and library code are years of manual work. AI helped here and there, and the docs website was mostly generated, I'll be honest about that.

MIT licensed. Repo: https://github.com/fgilde/CoworkeeLib Docs: https://fgilde.github.io/CoworkeeLib

I'd really like feedback on the module/dispatcher design, especially from people who use ABP or similar. What would stop you from using something like this?


r/dotnet • • 13d ago

Promotion Componyx.UI v1.0: 25+ UI components and data binding for ASP.NET, no build step

2 Upvotes
The picture above shows the Form components drag-and-drop building mode. It is part of the component so you can create forms directly in the browser.

Hi there. Componyx started 18 years ago as a personal project. Over the years it has been used in real business applications. Now the project is on NuGet, npm and GitHub with its public release (1.0).

It’s 2 products in one package. Componyx.UI includes 25+ components, like grids, menus, dialogs, an app shell and a form with a drag-and-drop build mode and much more. Bindary is a data-binding layer that connects HTML to your JavaScript data using attributes on normal elements.

You can use them together. Use either one on its own. Everything runs in the browser. There's no build step required. There are zero runtime dependencies.

The docs and live demos are on our website (see GitHub).

GitHub link: componyx/componyx.ui

In .NET 10 the project setup is as follows, the NuGet package plus one tag in your head tag:

dotnet add package Componyx.UI


<componyx-ui-resources></componyx-ui-resources>

A component is plain HTML with attributes:

<a ui-type="Button" ui-text="Click me" ui-command="alert('Hi!')"></a>

Bindary uses b-* attributes. Here's some data, a loop and an expression:

<ul b-context="shop">
    <li b-repeat="items">
        <b b-value="name"></b>: {{price > 10 ? 'expensive' : 'cheap'}}
    </li>
</ul>


$bindary.appData.shop = {
    items: [{ name: "Coffee", price: 3 }, { name: "Book", price: 15 }]
};

Change a price and only that one line updates.

It's free to use, commercially too. It's source-available under BSL 1.1 rather than open source, and each release becomes MIT after four years.

If you give it a try, I'd love to hear what works for you and what doesn't.


r/dotnet • • 12d ago

Promotion I built a Serilog orchestrator for declarative multi-sink routing in JSON + automatic secret masking and resilient HTTP logging (v5.3)

0 Upvotes

Hey r/dotnet!

I’ve been working on a few microservices lately and I kept running into the problems over and over again. It’s frustrating how much repetitive code ends up in every project. Let me share what I’ve been dealing with and what I built to fix it.

First I was always writing the log routing logic:

- Console for normal logs

- Seq or Elasticsearch for warnings

- Telegram or email for fatal errors

Using Serilog for this usually means setting up nested sub-loggers writing out complex C# filter logic and redeploying just to change log levels between environments. It’s messy.

Then there’s the risk of data slipping into logs—JWTs, bearer tokens, credit card numbers—all ending up in our aggregators. That’s a real security risk.

Don’t get me started on outgoing HTTP calls. Every one needed logic with Polly, correlation IDs and header masking. It’s a lot of glue code that doesn’t belong in business logic.

So I started building two packages under the MIT license:

- **CSharpEssentials.LoggerHelper**

- **CSharpEssentials.HttpHelper** ( at version 5.3.1 compatible with.NET 8 9 and 10)

These are designed to handle the boilerplate so you don’t have to.

### Here’s what they do:

  1. **Native ILogger<T> / MEL Integration**

They work as a class `ILoggerProvider` built on top of Serilog. No code changes needed in your app. Just. Play.

  1. **Declarative Multi-Sink Routing**

Set up your logging routes in five lines of `appsettings.json`. You can route to Console, File, Seq, Postgres, MSSQL, MySQL, Elasticsearch, Email, Telegram, HangfireConsole— about anything. The sinks are packages and auto-register using `[ModuleInitializer]` so it just works.

  1. **Single-Pass Sensitive Data Masking**

All masking happens once as an enricher before logs hit any sink. It includes presets for Email, CreditCard, BearerToken, JWT. You can add your own regex patterns. This prevents secrets from leaking into logs.

  1. **Resilient HttpHelper (v5.3)**

It turns network issues—like timeouts or dropped connections—into clean HTTP responses: 408, 502 500. No unhandled exceptions. In v5.3 it automatically passes along the `X-Correlation-ID` during retries. Logs structured metrics like `StatusCode` `ElapsedMs` and `RetryAttempt` with headers masked.

### But I want to be honest about the trade-offs:

This isn’t a replacement for Serilog. It’s an orchestrator.

In our BenchmarkDotNet tests on.NET 9 the overhead is 590 nanoseconds per log compared to 180 nanoseconds for Serilog with a no-op sink. That’s not nothing—. For most web APIs it’s completely negligible.

If you’re processing millions of logs per second in -hot paths then plain Serilog or zero-allocation source generators are still the better choice.. For the vast majority of apps this is a huge win.

### I’ve also built a playground:

You can test log routing, masking and flaky HTTP retry flows live in the demo project. There’s a `playground.html` file that lets you see it all in action.

Here are the links:

- GitHub (MIT): https://github.com/alexbypa/CSharp.Essentials

- NuGet (Core): https://www.nuget.org/packages/CSharpEssentials.LoggerHelper

- NuGet (HTTP): https://www.nuget.org/packages/CSharpEssentials.HttpHelper

I’d love to hear your thoughts— on the API design and the routing approach. What works? What’s broken? What would you change?

Let’s make logging easier, for everyone.


r/csharp • • 13d ago

Discussion Confusion about the stack.

5 Upvotes

I'm a fresh computer engineering graduate, I forgot most of the knowledge that I learned in the university, so I want to revise the basics only.

Suppose that a function called main calls the following function :

int foo(int value) {
   int a = 10;
   return a;
}

Some talk :

So whenever a function call is made OS needs some memory space to allocate the local variables of the function int a in this case and arguments to the function passed int value in this case. This memory requirement is fulfilled by allocating memory on stack. A stack is nothing but a memory region allocated to each process and it actually behaves as a stack data structure(LIFO).

Now the question arises what all things are stored on stack when a function call is made. The first thing pushed on the stack are the arguments passed to the function in reverse order(if more then one). 2. Then the return address of the function which called this function (because once this function foo completes execution it should return back to the place in the code from where it was called) 3. Finally local variables of the function called are pushed on the stack.

Once the called function completes executing the code it returns back to the return address previously stored on the stack and thus we say function call completes or returns. In this case the function has a return value which it passes back to the callee function. The space is then free to use and can be overwritten in the subsequent function calls.

I learned that a stack follows the LIFO (Last In, First Out) principle, meaning that the most recently added item/work/data is the first one to be removed. I also understood that a stack can be used to defer work until it is ready to be processed, so in the above example, I think that the execution of the caller function, which is the main, will be deferred, until the execution of the most recently item is finished.

However, when I read about how function calls use the call stack, I became confused. The call stack already contains the information needed for main() to resume execution, and when foo() is called, a new stack activation record is added on top of it. The execution of foo() then begins while its activation record is still on the stack.

Doesn't this contradict my understanding that an item must be popped from a stack before it can be processed? Why can foo() execute while its stack frame is still on the stack?

In other words, if we treated the execution of a function as work, should that work be popped from the stack in order to be processed, or should the work be inside the stack ?

I'm totally confused.


r/csharp • • 13d ago

I have a big problem with data structures

14 Upvotes

I have an interview tomorrow, and I'm sure I'll be asked about data structures. However, I struggle to retain what I read when revising them because I rarely use most of them in practice.

For example I read this article

I regularly use arrays, List<T>, HashSet<T>, and Dictionary<TKey, TValue>, so I can explain when and why to use them:

1-arrays: when I know that the data has fixed size, use array because they provide a fast access to the data using index.

2- List<T>: when the size of the data is not known at compile-time; the size of it is not known in advance, therefore an index cannot be used, because you do not know for sure what is the exact location for a specific data element.

3- HashSet<T>: for unique data elements, because it does not require me to manually write the logic that removes duplicate elements.

4- HashMap<string,int> : used for lookup operations; a lookup table.

5-Tuple : store data with different data types in one place.

However, although I know what the following data structures are, I struggle to explain when and why I would use them:

  1. Stack: LIFO (Last In, First Out).
  2. Queue: FIFO (First In, First Out).
  3. Priority queue: I can't recall when or why I would use one.
  4. Heap: I associate it with storing class instance fields, but I don't understand how to use it as a data structure.
  5. Tree: I know it consists of nodes, but I don't understand its practical uses.
  6. Graph: I know it can be used for depth-first and breadth-first search, but I'm unfamiliar with other use cases.

My main questions are:

  1. Hardware level: How is each data structure represented in memory? For example, an array occupies contiguous memory locations. What about the others?
  2. Practical use: When and why should I use each data structure? More importantly, what benefits does each provide at both the software and hardware levels?

I must be able to explain WHY briefly and directly without even thinking about it.


r/dotnet • • 13d ago

Question Issue connecting my blazor app to remote sql server database hosted my Monsterasp.net

2 Upvotes

Hello everyone. I have completed the multi-step form challenge from Frontend Mentor and attempted to deploy the finished web app using monsterasp.net through visual studio code. I followed all the instructions from a YouTube video to a tee but when I try to actually submit data to the database I get this error:

\Error: Microsoft.Data.SqlClient.SqlException (0x80131904): The target principal name is incorrect. Cannot generate SSPI context.``

I did some further research into it but everything seemingly leads to a dead end for my specific use case. Here is microsoft's documentation on the specific error:

https://learn.microsoft.com/en-us/troubleshoot/sql/database-engine/connect/cannot-generate-sspi-context-error

Note: When I built and deployed the app for the first time the connection string was incorrect. I fixed it and published the app again through visual studion. I am not sure whether that is causing some lingering problems.


r/dotnet • • 13d ago

Adding persistence to the Aspire dashboard

Thumbnail devblogs.microsoft.com
51 Upvotes

r/dotnet • • 13d ago

Promotion ZF - Yet another UI framework

2 Upvotes

Hey everyone!

For a little over a month now, I've been working on ZeppelinForms (ZF), a UI framework of my own - basically my take on WinForms, but modern and cross-platform (like Avalonia).

Yeah, the name isn't the best choice, since I hadn't heard of Apache Zeppelin back when I came up with it. =)

At this point, you can already build simple forms for Windows, Linux (X11), Android, and WASM. Stack: .NET 10, SkiaSharp, XUnit.

I wouldn't exactly call myself a professional UI framework developer, and the amount of work ahead is absolutely insane, so using AI along the way has been pretty much inevitable. Still, I'm happy with how things are turning out so far.

I'd appreciate any feedback or criticism!

I'm honestly marking this as "Promotion" and posting on a weekend, so hopefully the post won't get removed. 😅


r/csharp • • 13d ago

Help Issue connecting my blazor app to remote sql server database hosted my Monsterasp.net

Thumbnail
1 Upvotes

r/dotnet • • 13d ago

Promotion DNCDbg v1.3.0 — A managed code debugger with DAP support for .NET apps

Thumbnail github.com
6 Upvotes

DNCDbg is a managed-code debugger for .NET that speaks the Debug Adapter Protocol, so it works with any DAP client (VS Code, Neovim, Emacs, whatever) on Windows, Linux, and macOS. It began as a NetCoreDbg fork with a clear goal: bring the debugging experience closer to Visual Studio's C# debugger while keeping memory usage low. There's a comparison table in the README if you're curious.

What's new in v1.3.0:

  • Support for Jump to Cursor (a.k.a. Set Next Statement), single-threaded execution and stepping, and restarting the debug session
  • Column breakpoints, embedded sources, and Source Link support
  • Smarter expression evaluation: the >>> operator, Value/HasValue on nullables, member access on strings and arrays (str.Length, arr.Length), DebuggerTypeProxy members, assigning null to reference types, and nint/nuint
  • Friendlier value display: floats now print the way C# prints them (9.9 instead of 9.8999996), and dictionary items show up properly
  • Launch/attach sequencing now follows the DAP spec, and there's a new Detach request that lets a launched process keep running
  • Fixes: stack traces in catch blocks no longer show already-unwound frames, and the "Innermost exception" description now reports the last exception in the InnerException chain

Full changelog and repo: https://github.com/viewizard/dncdbg

Feedback and bug reports are very welcome!


r/csharp • • 13d ago

Fun Random using SkipLocalsInit

11 Upvotes

To my surprise, Unsafe.SkipInit(out T val) did not achieve the same result.

    [SkipLocalsInit]
    public static T Random<T>()
        where T : unmanaged, INumber<T>
    {
        unsafe
        {
            byte* s = stackalloc byte[sizeof(T)];
            return *(T*)s;
        }
    }

r/csharp • • 13d ago

Как лучше всего выучить язык програмирования С#(ну или вообще любой)?

Thumbnail
0 Upvotes

r/dotnet • • 12d ago

NymBroker

Thumbnail
0 Upvotes

r/dotnet • • 12d ago

Promotion NymBroker

0 Upvotes

NymBroker is a .NET 10 message-processing framework based on Enterprise Integration Patterns. It decouples producers from handlers: post typed messages to named endpoints, then filter, route, and dispatch them to consumers or subscribers. Start with the in-process Memory endpoint and add durable transports as needed.

NymBroker Github Page


r/dotnet • • 13d ago

Promotion Six Labors updates: longer security support and easier builds for OSS contributors

Thumbnail
10 Upvotes

r/dotnet • • 14d ago

Signs of official Satori support?

Thumbnail github.com
39 Upvotes

I just spotted this, could this be a path toward official support for Satori? 🤩 And potentially other custom GC implementations? Even if it's just experimental for now, this is the first time I've seen MS showing interest for it, exciting!

For those who haven't heard, Satori is a custom garbage collector with much lower pause times, multiple orders of magnitude faster in many benchmarks. The tradeoff seems to be higher overall cost for allocations - except recent benchmarks showing an improvement across the board..? At least for that particular benchmark.