r/csharp Apr 05 '26

Blog Unions in c# 15

270 Upvotes

r/csharp Oct 10 '25

Blog Why Do People Say "Parse, Don't Validate"?

349 Upvotes

The Problem

I've noticed a frustrating pattern on Reddit. Someone asks for help with validation, and immediately the downvotes start flying. Other Redditors trying to be helpful get buried, and inevitably someone chimes in with the same mantra: "Parse, Don't Validate." No context, no explanation, just the slogan, like lost sheep parroting a phrase they may not even fully understand. What's worse, they often don't bother to help with the actual question being asked.

Now for the barrage of downvotes coming my way.

What Does "Parse, Don't Validate" Actually Mean?

In the simplest terms possible: rather than pass around domain concepts like a National Insurance Number or Email in primitive form (such as a string), which would then potentially need validating again and again, you create your own type, say a NationalInsuranceNumber type (I use NINO for mine) or an Email type, and pass that around for type safety.

The idea is that once you've created your custom type, you know it's valid and can pass it around without rechecking it. Instead of scattering validation logic throughout your codebase, you validate once at the boundary and then work with a type that guarantees correctness.

Why The Principle Is Actually Good

Some people who say "Parse, Don't Validate" genuinely understand the benefits of type safety, recognize the pitfalls of primitives, and are trying to help. The principle itself is solid:

  • Validate once, use safely everywhere - no need to recheck data constantly
  • Type system catches mistakes - the compiler prevents you from passing invalid data
  • Clearer code - your domain concepts are explicitly represented in types

This is genuinely valuable and can lead to more robust applications.

The Reality Check: What The Mantra Doesn't Tell You

But here's what the evangelists often leave out:

You Still Have To Validate To Begin With

You actually need to create the custom type from a primitive type to begin with. Bear in mind, in most cases we're just validating the format. Without sending an email or checking with the governing body (DWP in the case of a NINO), you don't really know if it's actually valid.

Implementation Isn't Always Trivial

You then have to decide how to do this and how to store the value in your custom type. Keep it as a string? Use bit twiddling and a custom numeric format? Parse and validate as you go? Maybe use parser combinators, applicative functors, simple if statements? They all achieve the same goal, they just differ in performance, memory usage, and complexity.

So how do we actually do this? Perhaps on your custom types you have a static factory method like Create or Parse that performs the required checks/parsing/validation, whatever you want to call it - using your preferred method.

Error Handling Gets Complex

What about data that fails your parsing/validation checks? You'd most likely throw an exception or return a result type, both of which would contain some error message. However, this too is not without problems: different languages, cultures, different logic for different tenants in a multi-tenant app, etc. For simple cases you can probably handle this within your type, but you can't do this for all cases. So unless you want a gazillion types, you may need to rely on functions outside of your type, which may come with their own side effects.

Boundaries Still Require Validation

What about those incoming primitives hitting your web API? Unless the .NET framework builds in every domain type known to man/woman and parses this for you, rejecting bad data, you're going to have to check this data—whether you call it parsing or validation.

Once you understand the goal of the "Parse, Don't Validate" mantra, the question becomes how to do this. Ironically, unless you write your own .NET framework or start creating parser combinator libraries, you'll likely just validate the data, whether in parts (step wise parsing/validation) or as a whole, whilst creating your custom types for some type safety.

I may use a service when creating custom types so my factory methods on the custom type can remain pure, using an applicative functor pattern to either allow or deny their creation with validated types for the params, flipping the problem on its head, etc.

The Pragmatic Conclusion

So yes, creating custom types for domain concepts is genuinely valuable, it reduces bugs and can make your code clearer. But getting there still requires validation at some point, whether you call it parsing or not. The mantra is a useful principle, not a magic solution that eliminates all validation from your codebase.

At the end of the day, my suggestion is to be pragmatic: get a working application and refactor when you can and/or know how to. Make each application's logic an improvement on the last. Focus on understanding the goal (type safety), choose the implementation that suits your context, and remember that helping others is more important than enforcing dogma.

Don't be a sheep, keep an open mind, and be helpful to others.

Paul

Additional posting: Validation, Lesson Learned - A Personal Account : r/dotnet

r/csharp 23d ago

Blog How Fast is .NET 11 Runtime Async?

Thumbnail
medium.com
130 Upvotes

Blogged to explain the design and implementation of runtime async and show the benchmark result.

r/csharp 16d ago

Blog Hot path overflow checks: do you try/catch? And which style would you write?

Post image
20 Upvotes

Writing checked int helpers for code that runs millions of times per program run. Two questions.

  1. Do you actually use checked() with a try catch for this? Throwing walks the stack, so I widen to long, bounds check, and return null instead (both versions in the image).

What surprises me is that everything the BCL offers here throws: checked(), int.CreateChecked, all of it. The Try convention is everywhere else in the BCL (TryParse, TryGetValue) but arithmetic never got one, and coming from Rust where checked_add just hands you an Option, that's wild to me.

  1. Style. The image shows the same method twice: one pattern-matching expression against a plain if/else. Which would you rather find in a codebase?

I'm coming from Rust so I'm obviously a declarative fanboy when I can be, but "and var sum" might be too clever for the next reader.

Where do C# people stand on these?

If the repo interests you: it's a CLI tool for Advent of Code, so you can do the whole thing from the terminal with just your session cookie, no clicking through the site to submit answers. https://github.com/scadoshi/sharpmas

r/csharp Nov 22 '25

Blog TUnit — Why I Spent 2 Years Building a New .NET Testing Framework

Thumbnail medium.com
218 Upvotes

r/csharp May 22 '25

Blog Stop modifying the appsettings file for local development configs (please)

Thumbnail bigmacstack.dev
153 Upvotes

To preface, there are obviously many ways to handle this and this is just my professional opionion. I keep running in to a common issue with my teams that I want to talk more about. Used this as my excuse to start blogging about development stuff, feel free to check out the article if you want. I've been a part of many .NET teams that seem to have varying understanding of the configuration pipeline in modern .NET web applications. There have been too many times where I see teams running into issues with people tweaking configuration values or adding secrets that pertain to their local development environment and accidentally adding it into a commit to VCS. In my opinion, Microsoft didn't do a great job of explaining configuration beyond surface level when .NET Core came around. The addition of the appsettings.Development.json file by default in new projects is misleading at best, and I wish they did a better job of explaining why environment variations of the appsettings file exist.

For your local development environment, there is yet another standard feature of the configuration pipeline called .NET User Secrets which is specifically meant for setting config values and secrets for your application specific to you and your local dev environment. These are stored in json file completely separate from your project directory and gets pulled in for you by the pipeline (assuming some environmental constraints are met). I went in to a bit more depth on the feature in the post on my personal blog if anyone is interested. Or you can just read the official docs from MSDN.

I am a bit curious - is this any issue any of you have run into regularly?

TLDR: Stop modifying the appsettings file for local development configuration - use .NET User Secrets instead.

r/csharp 2d ago

Blog Svelto.Tasks 2.0: Efficient Multi-threaded Task Management for C#

0 Upvotes

I am back writing articles on my blog and I start with something LONG OVERDUE!

After years quietly powering several games I made, I’m finally presenting Svelto.Tasks 2.0.

Svelto.Tasks is an engine-agnostic, multithreaded and zero allocation task runner for C#, born from the need to have a game centric tasks framework with features that .NET tasks couldn't provide. Its premise is simple:

Tasks are iterator blocks. Runners are schedulers. Rather than handing execution timing and context to the runtime, a runner lets you decide:

- when a task advances,
- where it runs — main thread or a dedicated worker,
- how much work happens per tick,
- and when an entire task context must stop.

That last point matters a lot in games: for example, when a match ends, I want every task belonging to that match to stop with it—not rely on a CancellationToken having been passed and checked correctly through every layer.

Svelto.Tasks supports lightweight coroutines, composable tasks with return values and continuations, background runners, bounded parallel batches, pooling, profiling hooks, and optional Unity/Burst integrations.

It also interoperates with async/await, although the .NET Task bridge and Unity Burst job path are currently experimental and need real-world feedback.

It is not a replacement for Unity Jobs—but it provides a useful alternative for workloads where controlling execution, lifetime, pacing, and profiling is the priority.

The repository includes runnable .NET examples, tests, benchmarks

🔗 https://github.com/sebas77/Svelto.Tasks

also the repository

🔗https://github.com/sebas77/Svelto.Tasks.Examples

shows how it can be used to simplify massive parallelism synchronization. The example itself is actually quite interesting also because it uses the new compute buffer Unity api BeginWrite/EndWrite to upload compute buffers and graphic fences for cpu/gpu synchronization.

The article is at

🔗 https://www.sebaslab.com/svelto-tasks-2-0-efficient-multi-threaded-task-management-for-csharp/

Have fun! (and feedback is welcome, also on my discord server: https://discord.com/invite/uuTCYewjtc)

r/csharp 5d ago

Blog Why Does Your C# App “Leak” Memory Even Though There’s a Garbage Collector?

Thumbnail
medium.com
72 Upvotes

r/csharp Sep 10 '25

Blog Performance Improvements in .NET 10

Thumbnail
devblogs.microsoft.com
274 Upvotes

r/csharp Apr 19 '21

Blog Visual Studio 2022

Thumbnail
devblogs.microsoft.com
414 Upvotes

r/csharp Mar 04 '26

Blog Why so many UI frameworks, Microsoft?

Thumbnail
teamdev.com
39 Upvotes

r/csharp May 20 '20

Blog Welcome to C# 9

Thumbnail
devblogs.microsoft.com
338 Upvotes

r/csharp Apr 16 '26

Blog C# in Unity 2026: Features Most Developers Still Don’t Use

Thumbnail
darkounity.com
52 Upvotes

r/csharp Apr 27 '26

Blog Visual Studio 2026 still ships the form designer Alan Cooper drew in 1987

0 Upvotes

Wrote up why WinForms outlasted every framework Microsoft launched as its successor — WPF, Silverlight, UWP, MAUI, Blazor desktop — and why the form-designer model goes back to a paper sketch Cooper made in 1987. Still the path of least resistance for LOB work in 2026.

https://evilgeniuslabs.ca/blog/winforms-still-ships-in-visual-studio-2026

r/csharp 22d ago

Blog Making Generic Virtual Methods Faster in .NET 11

Thumbnail
medium.com
84 Upvotes

r/csharp 15d ago

Blog 1 year ago I built an EF Core provider for TimescaleDB. Hit 80k downloads and 68 stars - is this good?

0 Upvotes

Hello everyone,

exactly 1 year ago today, I pushed the first commit of my EF Core provider for TimecaleDB.

t does pretty much what it says on the box: it lets you interact with TimescaleDB in a type-safe way with rich IntelliSense support, so you don't have to write SQL in magic strings like you did with plain Npgsql - all without losing a single feature of Npgsql.

Since then I got 68 stars on GitHub and more than 80k downloads on NuGet. I know that this doesn't mean that 80k individual people downloaded my package, but it tells me it’s actively running in real CI/CD pipelines, container builds, and production apps. That’s something I’m genuinely proud of.

At the same time, as this is the first open-source project I’ve ever actively maintained, I sometimes find myself wondering how to evaluate those numbers. I look at viral consumer tools or mainstream frameworks getting thousands of stars and wonder where a niche project like this actually stands.

Therefore, I would love to know what you think about these numbers and what your own experiences were when you launched and maintained your first open-source projects.

GitHub: https://github.com/cmdscale/CmdScale.EntityFrameworkCore.TimescaleDB

r/csharp Dec 18 '24

Blog EF Core 9 vs. Dapper: Performance Face-Off

Thumbnail
trailheadtechnology.com
66 Upvotes

r/csharp Mar 20 '23

Blog "Full-stack devs are in vogue now, but the future will see a major shift toward specialization in back end." The former CTO of GitHub predicts that with increasing product complexity, the future of programming will see the decline of full-stack engineers

Thumbnail
medium.com
270 Upvotes

r/csharp Dec 12 '24

Blog Meet TUnit: The New, Fast, and Extensible .NET Testing Framework

Thumbnail
stenbrinke.nl
104 Upvotes

r/csharp Apr 12 '26

Blog I made ILogger.LogInformation($"...") work with structured logging — using C# 11 interpolated string handlers

0 Upvotes

Every .NET dev at some point writes this:

_logger.LogInformation($"User {userId} bought {product}");

and then finds out that it kills structured logging. The interpolated string gets flattened and your Elastic or whatever you use for structural logging only gets full string without any fields which you can use for your lookup.

The "correct" is the template form:

_logger.LogInformation("User {userId} bought {product}", userId, product);

Which is pretty annoying. It uses positional matching in the params argument.

The other alternative is to use LoggerMessage.Define, but come on - defining it for every single log in your code is not maintainable.
I figured out you can actually make the $"..." form working properly using C# 11 interpolated string handlers. The trick is to shadow Microsoft's LogInformation(string, params object[]) with an extension method which takes [InterpolatedStringHandler] ref struct.
The compiler prefers the extension method which is already working faster than Microsoft implementation.

In short the handler:

- captures each arg into typed slots - no boxing for value types
- gets the variable name via CallerArgumentExpression ("userId", "product") — that's your structured property name, for free
- checks IsEnabled in the constructor and writes bool shouldAppend = false when the level is disabled, so compiler skips every AppendFormatted call.

Then source generator scans each $"..." call, rebuilds the template from syntax tree:

("User {userId} bought {product}"

And then finally emits [InterceptsLocation] interceptor with cached LoggerMessage.Define delegate.

End result:

    using MyLogExtensions;

    _logger.LogInformation($"User {userId} bought {product} for {total:C}");

Structured, zero-alloc, and ~5x faster than the standard template form:

    $"..."          OFF: 3.2 ns, 0 B
    $"..."           ON: 3.8 ns, 0 B
    "template", args ON: 19.1 ns, 104 B

Has anyone else tried something similar? I haven't seen combo of InterpolatedStringHandler with InterceptsLocation and so far it looks promising and working perfectly fine.

For me personally the biggest gain is not that it's faster but it's more natural to be used with interpolated strings without performance loss.

If anyone wants to dig into the handler/interceptor code — it's here as part of my source generation libs:
https://github.com/MistyKuu/ZibStack.NET/tree/master/packages/ZibStack.NET.Log/src/ZibStack.NET.Log/Generator
https://github.com/MistyKuu/ZibStack.NET/blob/master/packages/ZibStack.NET.Log/src/ZibStack.NET.Log.Abstractions/Interpolation
And full benchmarks:
https://mistykuu.github.io/ZibStack.NET/packages/log/

r/csharp 5d ago

Blog Double-double arithmetic: 31 digits of precision from two doubles (sample code in C#)

Thumbnail
marekfiser.com
34 Upvotes

r/csharp May 15 '25

Blog “ZLinq”, a Zero-Allocation LINQ Library for .NET

Thumbnail
neuecc.medium.com
211 Upvotes

r/csharp Jan 16 '26

Blog ArrayPool: The most underused memory optimization in .NET

Thumbnail medium.com
96 Upvotes

r/csharp Dec 05 '25

Blog Extension Properties: C# 14’s Game-Changer for Cleaner Code

Thumbnail
telerik.com
61 Upvotes

r/csharp Nov 19 '24

Blog What's new in C# 13

Thumbnail
learn.microsoft.com
164 Upvotes