90 points runesoerensen 12 hours ago 189 comments
bob1029 14 hours ago | parent
SurajMishra 14 hours ago | parent
bjoli 14 hours ago | parent
I have also found c# async to be lighter than go's concurrency story, and dotnet11 is going to make that much more clear.
Now: I write software for fun, not for money.
SurajMishra 14 hours ago | parent
bjoli 13 hours ago | parent
For general concurrency where async doesn't suffice, go is nicer than C#, but hopac is nicer than go.
If go had proper concurrentML I am pretty sure I would use go a lot more. Again: this is for hobby projects where I get to choose freely.
abstractcontrol 11 hours ago | parent
i_s 14 hours ago | parent
kbolino 11 hours ago | parent
* = Technically, Windows now supports the UTF-8 "code page" where applications can use UTF-8 natively, but all NT system calls use UTF-16, so the conversion still has to happen somewhere
WorldMaker 10 hours ago | parent
The Runtime has explored attempting "UTF-8 native" string storage as a platform feature especially for Linux FFI, but yeah Windows using UTF-16 is still a compatibility issue where platforms themselves just don't agree.
pjmlp 14 hours ago | parent
Also Go is at the stage of C# .NET 2.0, and still plenty of lacking language features.
I really think the creator of C# made a disservice to the .NET community by picking Go for the Typescript rewrite.
fodkodrasz 12 hours ago | parent
WorldMaker 10 hours ago | parent
pjmlp 10 hours ago | parent
Static linking as the only way in most platforms, we moved into other mechanisms for a reason.
In Go the only way to do plugins, without shipping everything as source code is to use microservices, the more fashionable name for multiple process with OS IPC.
rewgs 9 hours ago | parent
Fans of Go (myself included) prefer this. The small feature set is a feature, not a bug.
wvenable 9 hours ago | parent
Go seems actively hostile to it's users, especially in comparison to C#.
zarlo 6 hours ago | parent
wvenable 6 hours ago | parent
But either way, this merely provides an excuse as to why Go is actively hostile to it's users. But backwards compatibility and language evolution are not mutually exclusive.
angrysaki 3 hours ago | parent
incidently 14 hours ago | parent
xnorswap 13 hours ago | parent
stackskipton 13 hours ago | parent
Sure, having a runtime is downside but difference in container size for your average CRUD App doesn't really matter. Performance IME is very similar.
Ops type here.
jeswin 13 hours ago | parent
bob1029 13 hours ago | parent
Put things like their remote debugging experiences side-by-side and you will quickly learn why some of us go for the Microsoft tools rather than the others.
ozim 12 hours ago | parent
I don’t have much experience with Go lang but what I have seen, there is lots of things one has to implement on his own. Which has its own merits, but to go from 0 to full fledged enterprise app you need more time.
retwakm4 12 hours ago | parent
Go is trying to be like C. Less language features (until recently...), so to solve problems you write more code. Intentionally simple language. Intentionally need a lot of code to implement something substantial. .NET seems more frameworks driven. Go traditionally has eschewed frameworks for doing stuff much like C tends to eschew framework type stuff and prefers smallest dependency reliance as possible.
zarlo 6 hours ago | parent
fabian2k 13 hours ago | parent
My experience with Go is a while back, before it got generics. While I liked the overall idea of a language with little syntax and a focus on simplicity, I didn't really like Go in the end. It was a weird mix of too low-level and high level code. It exposed low level details that I don't need to think about in C#, and it is missing convenient abstractions like LINQ.
Personally, I like async/await in C# more than Go concurrency. I know this is heretical here, but I don't care about function coloring or any of the abstract advantages of other concurrency approaches. Async/Await in C# works for me (in non-legacy code) and is easy to understand.
fodkodrasz 12 hours ago | parent
I'd beg to differ on the easy to understand... last time i worked with this stuff like ConfigureAwait only has cargo cults and no real good explanation, and wasn't covered in any recent version of eg. CLR via C#... Distributed tracing and thread management were totally bitten by async, also the way iterators and LINQ were broken... that was when I got off the train, as it broke the best abstractions for line of business code so that instead of designing an IO pipeline lazy developers could simple put Task.Run around blocking IO calls at the bottom of the codebas, and ... yeah, we are back at function coloring.
This brings me to: I winder for what kind of apps did you find it a delight, because for extensive data wrangling leveraging multiple calls it was a pain.
fabian2k 12 hours ago | parent
I'm using C# for the backend of a web application, not legacy but .NET Core from the start.
fodkodrasz 12 hours ago | parent
Something which was as easy as an IO call in the middle of a function running on a thread pool becomes a PITA if the IO call is cleverly async-ized (by wrapping the original sync IO method into a Task.Run(), but actually this is the better case!) ad then removed from the public API... (cannot recall the exact library, but it was a pain, as it was some core stuff, maybe vendored by MS themselves)
Also back then it caused us loosing correlation IDs as those were thread locals in traditional pre-async ASP.Net Core (think version 0.9-2.0 when I worked on that part, then up until core 4 and the async mania continuos broke readable calculation code in LINQ, TPL based performant data pipelines, etc...) and with async execution started to migrate between threads... If you needed high performance you already used threads, because it was not a classic web application, but a specialized optimization algorithm with a web api... and if you need more than CRUD, and use all the cores (and SIMD) to squeeze out all performance you have, you hit these problems right away. These all could be solved, but it actually broke stuff, a lot of stuff, as developers jumped on the fad, and it their sync code was turned into a .ConfigureAwait(false /* Microsoft blogs talk a lot about it without a clear explanation, so every cool kid does this */).GetAwaiter().GetResult()... then you some of your threaded code silently broken if you dare used Thread Locals... Faded memories, but that was when they f'ed up the C# language.
fabian2k 12 hours ago | parent
electroly 11 hours ago | parent
Indeed, you need a crapload of ConfigureAwait() in desktop UI code, and it infects all underlying libraries that might have to run inside a desktop app. The worst thing they ever added to our beautiful language. It's a dream to work in ASP.NET without needing to pepper every await with a ConfigureAwait().
That said, I don't agree with the characterization of ConfigureAwait() as un-understandable. We understand it. We just hate it.
pie_flavor 10 hours ago | parent
JamesSwift 13 hours ago | parent
netdevphoenix 12 hours ago | parent
moron4hire 12 hours ago | parent
mdasen 12 hours ago | parent
I'm going to talk about the second part first. .NET is often deployed with a JIT compiler runtime like Java. That means that hello-world scripts use a lot more memory than Go, but that difference becomes a lot smaller on real-world programs and .NET can use less memory than Go depending on what you're doing.
C#'s concurrency can also be more efficient than Go's since it's coroutine based async/await is a lightweight state machine rather than green threads. That's not to say Go is especially heavy or anything, but it is more overhead.
In terms of "efficient in syntax", Go has a lot fewer features. That's one of Go's biggest strengths and weaknesses.
Here's an example. With Go, you just have struct tags: strings of anything that can be attached to a field in a struct. Let's say you have a User struct and you want to make it so the JSON won't have the user's email in it. You do: Email string `json:"-"`. But what if you mess up and write "jsom" or `json:-` without the quotes? It's basically a meaningless string to the compiler. With C#/.NET, you have annotatons/attributes that are a part of the language and checked as types. You'd do: [JsonIgnore] public string Email. JsonIgnore is an attribute class so your IDE can help you.
There's a lot in Go where the answer kinda becomes "f-it, we'll just use strings instead of having something meaningful." Go talks about how important error handling is, but then you get an error from a function and it's basically just a string. If you're doing good error handling, you want to handle different errors differently, but that's not easy in Go. Frankly, it's not easy in most languages, but this is definitely an area where it felt like Go gave up on creating something good in order to get something out the door quickly enough that Google didn't cancel the project. In a language like Zig, errors are enums and you get exhaustiveness checking. With Go, someone could add another error state to something you're using and you'd never know - or they could change the phrasing of an existing error and you'd silently stop matching on it.
Go's lambda syntax is clunky. func(x MyType) string { x.ToString(); } vs (x) => x.ToString()
There's lots of stuff like that. I'm not arguing that Go is bad, but it has a ton less stuff and that's both a blessing and a curse.
999900000999 11 hours ago | parent
Golang is a fantastic delightful language, but it's still missing a lot of stuff that's existed in C# for years.
However, do you *need* all those .net tricks?
Golang is usually enough for a small project you need to build in a weekend. Scaling it to a mono repo with 200 developers might be a bit difficult
pie_flavor 11 hours ago | parent
lynguist 11 hours ago | parent
Go is for me just a, hmm, concurrency programming language. Its popularity stems just from being pushed by Google, and the cosmetics of using braces. Despite what pundits say, it's completely and utterly not like C.
While C# is a successful and comfortable everything-language. It is blazing fast, has amazing tooling, you can get going to prototyping, then enterprise code, its serverside handling is excellent. It has many low level features and built-in data structures. It's I would say preferable for almost any kind of work except scripting. (I really don't like C# scripting.)
delta_p_delta_x 10 hours ago | parent
PowerShell says hello :)
YuechenLi 10 hours ago | parent
Go's advantage is mostly the fast compile speed, goroutines, profiling, and a very opinionated formatter. Neither has an overwhelming advantage over the other though.
zarlo 6 hours ago | parent
Some example.
Open API document generation using type handlers doing this in go was a pain in .net is comes out of the box.
A lot of people underestimate the power of extension methods.
.nets metadata system is compiled time safe where Go is not and this has burnt me a lot.
I really like go for command line tools Small binary sizes I lovely.
go's standard library is significantly more hackable than .nets there have been a few things where I've ended up using Go because to do it in .net would require me maintaining a fork of the standard library.
Go makes composing data insanely simple. where in .NET you can have an equivalency but it will be done via interfaces.
Go's Dark Type System is both great and really annoying.
C#'s stricter type system when it comes to interfaces can be really handy as that can be used as metadata to change how data is processed and enforce compile time checks.
wofo 14 hours ago | parent
pjmlp 14 hours ago | parent
jayd16 13 hours ago | parent
pjmlp 13 hours ago | parent
https://github.com/dotnet/runtimelab/issues/2398
Be sure to read all the way to the bottom,
shellac 13 hours ago | parent
WorldMaker 11 hours ago | parent
There have been smaller runtime improvements like this one in recent releases, but this one seems a big one to point to to prove that the runtime is truly growing at a faster and more interesting pace than the old days.
tikotus 7 hours ago | parent
electroly 5 hours ago | parent
> One especially useful result is a clearer live call stack. Profilers and debuggers can show the asynchronous methods themselves instead of the infrastructure used to execute them. This is a distinction from exception stack traces, which already hide much of that infrastructure.
Maybe exceptions will still gain some benefit because it doesn't have to physically walk so many frames? But the string at the end is likely to be roughly as big as before.
HexDecOctBin 14 hours ago | parent
gdwatson 14 hours ago | parent
netdevphoenix 12 hours ago | parent
moron4hire 12 hours ago | parent
The tooling ecosystem in Python is just so bad that I can barely stomach it after spending the last 20 years in .NET. At times, when supporting analysts at work wanting to write a little glue code, I've found their main complaint about C# is "curly braces" (which seems like a really odd thing to complain about, but ok) and I've found it easier to teach them a little VB than to figure out whatever the hell is going on with dependency and runtime version management in Python.
And then, for the folks who go deep on Python for ML tasks, I've mostly found them caring now about specific libraries than the language itself. I then show them how .NET has equivalent or better libraries available and that a lot of the code-golf stuff they do in Python has a much cleaner version in F#.
pletnes 11 hours ago | parent
Scharkenberg 9 hours ago | parent
delta_p_delta_x 10 hours ago | parent
Or PowerShell if you want to hash out something really quick.
kvemkon 12 hours ago | parent
giancarlostoro 12 hours ago | parent
I wound up going to college after working retail at Disney, then after college, my first job was supposed to be C# but they didn't have the project approved, so I got my first exposure to Python - which I loved, then JavaScript - which I hated but have a love-hate with to this day, and finally C#, but it wasn't .NET 3.5 no, they started using .NET Core, which was... something else, lots of teeth pulling during the original .NET Core days.
So many wonderful projects made with .NET my only complaint is I wish Microsoft would make a cross-platform GUI stack they'd actually stick to, and make it work on Linux too. ;)
I know there's alternatives but nothing beats telling your coworkers "lets just use the built-in" when choosing a GUI stack.
Ungh 12 hours ago | parent
Once burned, twice shy.
npodbielski 12 hours ago | parent
WorldMaker 11 hours ago | parent
That concept of "define an RPC interface and let the platform fill it" was ancient before WCF and continues to this day (I've got a bunch of tabs open for Cloudflare Durable Objects right now). The legacy problem with WCF was not but long term backward compatibility with the Bindings abstractions and XML config junk and SOAP Stack RPC. Without WCF native in the box in .NET 5+ it is harder (but not impossible) to build SOAP RPC monoliths. But so few businesses actually need SOAP and can't just switch to something more RESTful.
Silverlight was maybe ahead of its time given the growing popularity of Blazor WASM.
pjc50 12 hours ago | parent
alternatex 11 hours ago | parent
The most supported UI frameworks from MS for Windows are WPF and WinUI 3. UWP is dead and WinForms (even though closest to something native to Windows) is probably going to end up in the land of forgotten (sorry nostalgic Windows devs, you have to face it eventually).
A "mess" is an understatement when the people who themselves develop Windows desktop apps have trouble explaining the landscape.
pie_flavor 11 hours ago | parent
delta_p_delta_x 10 hours ago | parent
Everything boils back down to Win32, including WPF, WinForms, WinUI2, and WinUI3.
pjc50 6 hours ago | parent
https://learn.microsoft.com/en-us/windows/apps/desktop/moder...
flykespice 3 hours ago | parent
Ungh 10 hours ago | parent
verst 12 hours ago | parent
feoren 9 hours ago | parent
I don't understand this. I love C# as a language, but the idea that everyone is forced to upgrade every single library every 2 years is beyond unreasonable. I've recently run into a situation where some configuration behavior deep in ASP.NET just randomly changed between .NET 8 and .NET 10, and broke things. A runtime exception, not a compile-time one. What else is subtly broken in a DLL referenced by a reference of a reference? You may never know.
It seems like every software engineer has forgotten that code is ultimately math. All of the greats understood this, from the times of Alan Turing through the 1990s. Then all of a sudden it became some sort of a toy, a game for 20-year-olds to one-up each other, to move fast and break things. Somehow, as software development matured, it became less of a serious discipline. Now, we have an entire ecosystem where it's just accepted that any line of code you've ever written may just randomly break every 2 years. You can no longer just write a small C# library and expect to to continue to work forever. It's completely unacceptable in my view.
CodeCompost 11 hours ago | parent
giancarlostoro 11 hours ago | parent
So about that... when I started using .NET Core, it was bleeding edge and shiny, but it was to rewrite a Silverlight application, the only way to run it was Firefox ESR 54 (I think it was 54?) we thought "oh this is easy" only to find out that it was a colossal nightmare, EF didn't support some things, including Shapefiles, we had to force the support, get back a WKT from SQL Server, and send one back when we did updates, basically Entity Framework was mostly useless.
I also reverse scaffolded the existing database into EF compatible classes, so that saved us a ton of effort, the original idea was to be backwards compatible.
Best part? It never got used, when we found out they weren't using the project, my boss said, screw it, lets remake it in Python I know we can build it up quicker, and sure enough, it was done quicker than the C# rewrite, fastest rewrite I ever did, because he figured out the key things they actually needed, and trimmed the requirements to just those key things.
Sometimes rewrites don't need to be 1:1 especially if it's an internal only tool.
Anyway, lots of blood, sweat, tears, stress, etc from me as it was my first job in tech.
starik36 10 hours ago | parent
Boy do I have good news for you (I am half kidding). OpenSilver project lets you compile your Silverlight code to Web Assembly or iOS/Android/Windows/Mac.
You can dust off your code now.
dude250711 12 hours ago | parent
Sinofsky left a lasting damage. The way things go with LLMs, it might be now pure app-specific Rust instead of any common frameworks....
HeckFeck 12 hours ago | parent
I know this may as well be beseeched of the King of Nod, but if they just made WPF cross platform I'd be delighted beyond words.
giancarlostoro 11 hours ago | parent
XAML was supposed to become an open spec, not sure why they have so many teams making so many different ways to make UIs. Then there's those "Windows 8" apps, or the "Universal Windows Apps" which are poorly named, you cannot run any of them on previous versions of Windows, if anything Win32 apps are universal apps.
anthk 11 hours ago | parent
https://github.com/iBobX/RapidR
Not compatible, but you can use it in a cross-platform way.
aryonoco 12 hours ago | parent
Not quite discriminated unions, but close. With an exhaustive checker with switch statements.
Now if only it made creating unique types easy, so I wouldn’t have to use a library like VOgen, the language would be nearly as good as F#
Metasyntactic 9 hours ago | parent
You can start reading through it starting at: https://github.com/dotnet/csharplang/blob/main/proposals/dis...
Definitely want to move to get this in asap :)
gkbrk 12 hours ago | parent
doomroot13 11 hours ago | parent
https://devblogs.microsoft.com/dotnet/performance-improvemen...
kvemkon 11 hours ago | parent
GaProgMan 11 hours ago | parent
They burried the lede on this one.
- .NET 10 is end of life'd on Nov 14th, 2028 - .NET 11 is end of life'd on Nov 9th, 2028
Which means anyone who upgrades to 11 has fewer days of support. But the idea is that you'll upgrade to 12 as soon as it's RTM'd.
The problem with that is I have clients who refuse to budge from 2.1 (or even upgrade to the 2.1 re-release: 2.3).
voidmain0001 11 hours ago | parent
kbolino 11 hours ago | parent
[1]: https://www.oracle.com/java/technologies/java-se-support-roa...
whaleofatw2022 11 hours ago | parent
jongalloway2 4 hours ago | parent
https://dotnet.microsoft.com/en-us/platform/support/policy/d...
hvb2 7 hours ago | parent
I think Microsoft regretted those long (10 years) support guarantees they had for .net framework. In the end, it probably slows you down in terms of innovating
kbolino 6 hours ago | parent
Anyway, the critique was less about the exact length of LTS, and more about the lack of significant difference between LTS and STS.
pixl97 11 hours ago | parent
Not really for any groups that commonly use .Net. Even numbers are LTS and odd numbers are not, or at least it's been this way for a while.
>I have clients who refuse to budge from 2.1
Give me their names, sounds like it would be easy to penetrate them again and again and again with AI.
WorldMaker 11 hours ago | parent
foepys 11 hours ago | parent
2.3 on .NET Framework reaches end of life on 2027-04-13, so upgrades have to happen soon.
xnorswap 8 hours ago | parent
It's still in support, and led to one of the most confusing release announcements in history: https://devblogs.microsoft.com/dotnet/servicing-release-advi...
ASP.NET Core 2.3 does go end of life in April 2027 however: https://devblogs.microsoft.com/dotnet/aspnet-core-2-3-end-of...
sire-vc 3 hours ago | parent
jdw64 11 hours ago | parent
Rohansi 10 hours ago | parent
jdw64 9 hours ago | parent
In fact, desktop apps are mostly used for factories or Windows-only programs, which is a bit disappointing. It's a very good language for making games and the most widely used language for factory programming, but whether to build a product with it is a bit ambiguous. I'd use it when making a program for a specific customer, but for a product I'd probably use TypeScript.
Rohansi 7 hours ago | parent
> On the server side, TypeScript is actually better
I like TypeScript but I'd never pick it over C# on the server side unless I had to do React SSR for some reason.
jdw64 5 hours ago | parent
I often build ERPs too, and for delivery I usually use TypeScript with Electron. C#'s biggest problem is mobile support. It's very strong on the game side, but weak on most phones. TypeScript, on the other hand, uses a bit more memory but is easier to wrap for mobile. You can just use Capacitor alongside Electron.
In my case, it's not a huge project—it's usually a small ERP dedicated to a local company in the region, so even if there are many employees, it's often only 100–200 people. At that scale, TypeScript holds up well enough. (For factory MES, there are tens of thousands of data points, but in that case it's usually fixed to C#.)
In this context, the mobile option in the ERP is good for charging customers, and it offers good extensibility as a reference option.
Unless WASM performance improves, there's still a bit of latency. On top of that, in my country there are few maintenance personnel.
wallstop 3 hours ago | parent
Rohansi 2 hours ago | parent
I do agree that it's hard to beat web tech though. Great support across all platforms. Just don't forget to optimize.
1a527dd5 11 hours ago | parent
Be aware
(decimal)0.1
// .NET 10: 0.1
// .NET 11: 0.1000000000000000055511151231xnorswap 11 hours ago | parent
(decimal)0.1f
0.100000001490116119384765625rednb 9 hours ago | parent
bazoom42 9 hours ago | parent
snkline 8 hours ago | parent
Hell, on the rare occasion I've needed to use a decimal literal in code, I just use a decimal literal: don't do (decimal)0.1, just use 0.1m.
FearNotDaniel 8 hours ago | parent
kevin_thibedeau 4 hours ago | parent
mgdev 11 hours ago | parent
However they still suffer from an incredible branding problem.
It's really too bad because as a runtime it's fairly incredible, and F# in particular is fun to work with. They also have good cross-platform support and tooling, which they didn't have a number of years ago.
Combine that with the fact that nobody really writes code anyway thanks to AI, and this could be a slam dunk runtime for an AI-native development environment.
But it will never happen.
CharlieDigital 11 hours ago | parent
> ...this could be a slam dunk runtime for an AI-native development environment.
I wrote this in my other comment, but I really think that C# is an underappreciated language and tooling stack for AI. - Roslyn analyzers (C# code analyzers written in C# that run on the C# compiler)
- Simple, stable tool chain
- Language has largely been stable and backwards compatible for the two and half decades of its existence
- Now have a very, very good type system that promotes good practices
- Very good corpus of docs
Something else I stumbled upon recently is hooking CSharpRepl directly into DI and handing that to an agent: https://fuqua.io/blog/2026/06/injecting-a-csharp-repl-into-a...It's actually crazy what the agent can do with that.
ozim 10 hours ago | parent
CharlieDigital 11 hours ago | parent
Some folks out there still think .NET is Windows only. Some folks out there haven't looked at C# since the .NET Framework days. Some folks out there are still salty about some of Microsoft's decision around OSS (debugger, hot reload fiasco, etc.)
But day to day working with C# and .NET for backends? It's really fantastic. AI seems to like it a lot and a lot of tools for agents to go HAM. Roslyn analyzer, source generators, workable hot reload (for a compiled language), tons of really good docs from Microsoft, generally low variance and high consistency from codebase to codebase (e.g. encountering Drizzle vs Prisma vs TypeORM vs Kysely vs ... in Node land).
My previous team switched from TS to C# and F#[0][1] and it was a blessing; a lot of the platform ops have been simplified. It's just one very solid tool chain and packages are generally stable (a lot less effort on maintaining platform config/tooling and more focus on just building). First party packages get consistent security updates and C# doesn't have nearly the same level of exposure to transitive packages that one encounters with JS/TS ecosystem.
C# feels like a really solid choice in the age of AI coding because of it's general stability, strong static analyzer, insistence on types, and really good tooling. Not right for all use cases (e.g. CLI, serverless functions), but fantastic for backend APIs.
If you're looking to do AI with/on C#, I wrote about some of my experience with making codebases successful for AI[2].
[0] https://engineering.usemotion.com/moving-off-of-typescript-e...
[1] https://typescript-is-like-csharp.chrlschn.dev/
[2] https://chrlschn.dev/blog/2026/08/the-unexpected-ai-stack-cs...
jodrellblank 10 hours ago | parent
CharlieDigital 10 hours ago | parent
We shifted all new product backend build to C# (because at this time last year, we were still "AI assisted" and deemed F# too foreign for most devs to read well), but all internal tooling was built on F#.
By maybe May of this year? We had multiple F# backend codebases, fully AI generated. Only one person on the entire team had worked with F# by hand. Several things work in F#'s favor even though it has a lot less representation in training: 1) the people that write F# really love F# so the code out in the wild is going to be better quality (hunch), 2) F# is a bit more terse/dense than C# and less noise in context, 3) F# benefits from the same tooling stack, 4) F# type system is still a bit more expressive than C#.
I know C# deeply so I know what good looks like and I know how to get agents to write good C#. F# I'm less familiar with, but we had great success with it.
YuechenLi 10 hours ago | parent
CharlieDigital 9 hours ago | parent
rspeele 20 minutes ago | parent
This in contrast to C# where, within one .csproj, there is no "order" and all classes and methods are able to mutually reference one another.
The F# way creates an annoying housekeeping step of maintaining file order, and would be a nightmare to do with manually edited .fsproj files (I have only ever written F# with an IDE), but IMO, it is worth it. On the reading side, it makes it easier to understand how a project you've never read before is structured, since you know the order of the F# source files also must be the bottom-to-top layering of the code. On the writing side, it sometimes causes one to rethink the architecture and simplify it to minimize the number of mutual declarations.
rednb 9 hours ago | parent
doublepg23 10 hours ago | parent
stevefan1999 10 hours ago | parent
The corporate history of C# is undeniably strong, and even till this day in modern C#, they still have a lot of legacy components in it, like AppDomain, APM and MarshalByRefObject.
It is also unfortunately that C# has largely lost in the AI race, that it failed to gain tractions from AI developers despite heavy investments from Microsoft. Early AI stuff like Semantic Kernel actually included C# as its primary languages besides from Python. Nowadays it is not mentioned so much and the default is just Python but perhaps it really isn't a fair comparison due to the gravity of Python in AI as a whole.
Yet for another fact that even within Microsoft, Rust wins over C# for agentic development, is a clear indication that C# has lost a meaningful place in software development as its former parent started to berate it as well. TypeScript is rewritten in Go rather than C#, and consider the fact that Anders Hejlsberg made both C# and TypeScript...
Sure, maybe Bing and a large part of Azure and Xbox services still have heavily relying on it, probably because of ASP.NET Core and Orleans, but outside of the two Microsoft greenhouses, it is a free for all battle royale where C# don't even have a chance of being picked at due to being too weak.
I even tried to contribute a C# SDK to the Restate project, but the maintainers actively rejected it due to them not being familiar and refused the handover. They said they will consider if there are commercial fundings backing it, then they would starting to consider (that's even with money attached they would still think about it). This also shows how unpopular C#/dotnet is among open source development and failed to build hype. The same Restate project even have a Java SDK for it, so it is not like they can't handle C#, they just didn't like to.
The last few thing C# is good at is just Unity I'm afraid, and that is also dying too as Unity is also not doing so well lately.
CharlieDigital 9 hours ago | parent
For web API backends and MCP servers, I firmly believe C# is the better choice.
For AI use cases (as in make calls to LLMs), there's not much difference, IMO from Python and C# and TypeScript. At the end of the day, those are all just REST API calls and SDKs are mostly wrappers around it.
For LoB apps where the AI/LLM is just one small leg of the actual flow, C# is still a winner, IMO, because of how good the overall stack is (e.g. EF Core). Orleans (actor model framework) is also super interesting and I'm exploring some memory/communication system based around it.
moron4hire 3 hours ago | parent
raincole 10 hours ago | parent
It's a good language though. The latest trend of hating OOP is unjustified/overreaction. I do write Rust too and I am not really convinced that traits are better than shallow inheritance + interface-oriented classes.
CharlieDigital 9 hours ago | parent
> Being a Microsoft product is such a heavy baggage
Which I always found ironic because TypeScript (from the same guy that created C# even!), VS Code are both Microsoft. Microsoft also makes big contributions and investments in Postgres and Python as well.bbkane 7 hours ago | parent
raincole 7 hours ago | parent
JavaScript is one of the most common compile targets. "Who's the better JavaScript" was the most contested field a decade ago. These are not just toy languages - Facebook has Flow and Google has Dart. Both companies are far more web-adjacent than Microsoft. Yet Typescript won. It won so hard that we feel it has no competitors today.
MiroslavPokorny 3 hours ago | parent
angrysaki 3 hours ago | parent
edit: I think it was considered, but go was a better fit
YuechenLi 8 hours ago | parent
I got so worked up by it I built my own TyepScript compiler with my clankers in C# to prove that it can be done, my revival of the Common Language Runtime concept, project Copeland:
https://github.com/yuechen-li-dev/copeland
Currently, Copeland compiles a dialect of TypeScript to JavaScript, C#, WASM via Blazor WebAssembly, and NativeAOT, runs in csproj, and uses xUnit.NET for testing framework.
(The other reason is that Microsoft still refuses to do the obvious thing in .NET 11 and take the best part of Rust and let enums be `match`ed, despite the fact that both TypeScript and C# have weak enums historically, so I added payload enums to my TypeScript dialect because Microsoft won't.)
sysmax 36 minutes ago | parent
sfn42 9 hours ago | parent
Other than that I totally agree with everything you said.
CharlieDigital 9 hours ago | parent
> I think C# would be a great choice for both CLI apps and server less functions.
Really? I feel those are the two areas where it falls short. CLI apps and serverless both value cold starts and C# is not great at it because of the JIT overhead. The immaturity of NativeAOT ecosystem on C# was cited by Anders as one of the reasons the TS team chose to rewrite in Go.raincole 8 hours ago | parent
qingcharles 5 hours ago | parent
macintux 43 minutes ago | parent
I may have to play with F# for that.
smoe 9 hours ago | parent
I'm especially interested in exploring F# as a concise, non ambiguous way to communicate definitions between humans and agents, somewhere between writing code like the olden days of yesteryear and describing things in English prose.
CharlieDigital 9 hours ago | parent
smoe 9 hours ago | parent
Yes, the plan is essentially 100% AI code with a small team of programmers and domain experts from other technical backgrounds. But still depends on a few things on the business end before I can really kick it off. More of an exploration until then.
angrysaki 3 hours ago | parent
CharlieDigital 2 hours ago | parent
But the gist of it is that I wire it up through Aspire (don't need to, but makes it nice) to set the environment variable on my main app host. Then the agent can run `csharprepl` commands directly via CLI and read/mutate the running application state directly via the service provider (DI container)
I have a small set of utility functions to access the DI container with common patterns like creating a scope for scoped services: https://github.com/zeeq-ai/zeeq-app/blob/main/src/backend/Ze... (optional, but useful)
And a skill: https://github.com/zeeq-ai/zeeq-app/blob/main/.agents/skills... (also optional, but cuts down on agents relearning the #wrap and #replace behavior)
I recommend you "train" the skill like I do in my the blog post. Basically ask the agent to get an instance of an object from DI like a repository class or your DbContext and have it perform some operations. Have it wrap a function and add logging. Have it replace a function. Then once it learns how to do this, have it write the skill bespoke to your project.
I strongly recommend that you try it "by hand" one time via blog of CSharpRepl author: https://fuqua.io/blog/2026/06/injecting-a-csharp-repl-into-a... If you try it manually one time, it clicks what the agent is doing and why it is so powerful (because the agent accesses and modifies the running application state without a compile).
EMM_386 8 hours ago | parent
I still choose .NET as the go-to whenever I can. On Windows or Linux.
I think the baggage view was valid for a while - but now we have a new generation of developers who only know about .Net Core and may not associate the Framework years in quite the same way.
qingcharles 5 hours ago | parent
rsalus 4 minutes ago | parent
jiggawatts 8 hours ago | parent
Opinionated in a good way, which means almost all C# apps have the same parameterisation with environment variables, command line, and config files. It’s all very systematic, consistent, but flexible and pluggable.
“Node has that too!” you’re about to say. Lol, no. It has bits and pieces the devs have to wire themselves, which means a fleet of vaguely related apps made by independent teams will have wildly different config styles. Good luck consistently making all of them pull API client certs from KMS or Key Vault, or whatever!
OpenTelemetry is now baked in to the core components and rapidly spreading through other libraries.
Excellent “pervasive” system APIs for spans, traces, metrics, and logs means that the sources are omnipresent and very rich, going back decades. Even very old third party libraries are often a breeze to instrument.
Debug snapshots from production crashes on App Service feels like cheating.
Built in container build outputs with no extra tooling.
Sane defaults for its package manager means far fewer nasty security surprises.
Far more first-party “coverage” of essential capabilities in the optional Microsoft packages so you don’t have to resort to NPM where your security-critical code is written by Sergei and support is “LOL Wut!?”
A GC that automatically responds to container limits instead of the host limits.
It uses thread pools for async tasks in most configurations so whole categories of production-time issues that occur with single threaded runtimes just doesn’t happen.
Etc, etc…
christophilus 6 hours ago | parent
fhn 2 hours ago | parent
tester756 10 hours ago | parent
but job offers are kind of boring :/
SirMaster 10 hours ago | parent
int122 8 hours ago | parent
Have to agree, PHP codebases also were nice organized, bigger repos, mostly web apps / company backoffice apps and so on. Personally, products were more interesting.
With today dotnet state, it really suits well for API development / microservices / integrations / we had many workers - jobs running, queue subscribers, K8S, good test coverage, open telemetry.
Even migrating from .NET Framework wasn't so big pain.
Job postings sucks nowadays for all stacks.
jotato 10 hours ago | parent
But I'm on linux now. If I wanted to pick up back up then what should I be using?
codeulike 10 hours ago | parent
asteiger 10 hours ago | parent
drmathias 10 hours ago | parent
rafaelmn 10 hours ago | parent
pletnes 10 hours ago | parent
FearNotDaniel 8 hours ago | parent
Kuinox 8 hours ago | parent
int122 8 hours ago | parent
I prefer VS but for the performance, I use VS Code. Unable to work in Rider on 32 GB RAM.
raincole 8 hours ago | parent
peder 6 hours ago | parent
gabeh 10 hours ago | parent
zerr 9 hours ago | parent
feoren 9 hours ago | parent
Either you should not be forced to upgrade, or backward compatibility should be guaranteed -- not both. But Microsoft is happy to say "hey, we're going to completely abandon support for every version of .NET every 2 years, and if you can't keep up to date then everything that goes wrong is all your fault." Meanwhile, they have no problem breaking your code.
This essentially kills the possibility of just writing a bunch of small, useful libraries, and having them be useful forever. It is the antithesis of a healthy software ecosystem. Are you really expecting that every single open source library that is referenced by a reference of your references is going to be maintained in the face of breaking changes every 2 years? If not, then upgrading your version of .NET is just a gamble that things won't randomly break. But you must upgrade, or you're a bad developer who's leaving your apps vulnerable and every automated security checking system in the world will yell at you about how awful you are. You must upgrade everything you have ever written every two years, and hope that every library you've ever depended on does the same, or you are putting yourself at risk of some breaking change sneaking its way in, or leaving yourself vulnerable to a critical security issue that Microsoft refuses to back-apply.
I cannot understand why I'm the only one shouting from the rooftops about this. It's completely unacceptable to me.
raincole 9 hours ago | parent
zarlo 6 hours ago | parent
ablob 8 hours ago | parent
Rapzid 5 hours ago | parent
Hobrot 34 minutes ago | parent
dead_hn_theory 20 minutes ago | parent