One thing I appreciate about C# and .NET is how well they resist codebase rot. In some other languages, I often encounter situations where the development environment needs to be completely recreated—sometimes due to an updated interpreter version or other breaking changes. If you've been away from the codebase for a while, chances are you'll need to make modifications just to get it running in a more recent environment.
With .NET, this issue is much less pronounced. While occasional adjustments are necessary, the environment is largely self-contained, minimizing the overhead required to get things running. As long as the .NET SDK is installed, running dotnet restore is usually all it takes—even when moving the codebase to an entirely new machine.
Some third-party libraries evolve more rapidly than others, but the core .NET libraries remain remarkably stable. More often than not, you can transition between major versions without needing to modify any code.
If I were starting a long-term project that required ongoing maintenance, C# would be my top choice. For quick scripting needs, I’d lean toward Python or PowerShell. In fact, PowerShell itself is another reason I appreciate .NET—it shares many concepts, and knowing .NET makes it easier to understand PowerShell. Plus, since PowerShell can directly leverage .NET libraries, it offers powerful scripting capabilities. I was thrilled when PowerShell became cross-platform, much like .NET itself.
This is going to sound really unfair, but compared to some of the more hip languages, the .NET/JVM ecosystems feel a bit more like they have adults at the helm who at least try to maintain backward compat. They’re also stodgy as hell sometimes, but I’ll take that. There’s a real difference in culture that manifests in both what is made and what is held up as good engineering. And that has an effect of raising the bar on what is acceptable from an ecosystem POV.
Yes, it’s possible you’ll have to deal with Enterprise-y code sometimes. But, it’s usually your team’s choice as to what is written. Also, people don’t seem to complain quite as much about it when they encounter it at a FAANG elsewhere that tries to do “good” engineering, but that’s another discussion. :)
Compared to JS, Go, Java, etc. I feel like C# evolves significantly faster and the team is faster to validate, implement, and deliver improvements to the language.
I think this is also why some folks who tried C# say 5-6 years ago have no idea how fast the language has evolved for the better.
That's not unfair at all, I think it's a fair assessment. Industrial tools should have adults at the helm. People who care about longevity and robustness foremost. About delivering quality and stability where the main value points of a language are.
Yes, they place a strong emphasis on backward compatibility, particularly with language features. This allows new C# language features to be gradually introduced into a codebase without disruption, which is especially valuable in enterprise environments. It may feel stodgy, as you say, but they continue to add interesting features with each C# release, striking a good balance between stability and innovation.
Not sure why you’re downvoted. Happy to hear your experiences good and bad with it.
My quick take: Kotlin is a joy to write in, Jetbrains tooling is pretty good (though a bit dicey lately), build systems seem a bit eh, and the whole ecosystem is a bit too locked on spring boot. I use Quarkus, which has been pretty good, but it is much smaller in terms of user base.
Upgrades between modern .NET (Core) versions are simple and painless. It’s just a single-character change in the .csproj file, plus maybe upgrading some dependencies (but old versions will usually work).
Upgrading from the classic .NET Framework to the modern .NET is usually a long process. Simple console apps, desktop apps, and libraries might be doable with an automated csproj upgrade. But Web apps require a rewrite from scratch, because the old ASP.NET is incompatible with the modern ASP.NET Core.
This hasn't been the case for me at all, the jumps between lts releases have burnt a lot of my time figuring out how to fix broken things. Though c# is definitely my favourite language to work in :)
What difficulties did you experience? I’ve upgraded many projects from ancient C# v2 and more modern versions. There are always some things that need to be addressed, but as long as you look at the changes from the one version to the next it’s easy enough to figure out what needs to be changed. Most modern IDEs will point out the issues in an upgrade report.
Bit hazy now, but at work every time an LTS change happens the first team to do it publishes it's notes on how it fixed various issues. Off the top of my head I remember a problem with swagger, but to be fair that's a third party lib. Problems with other 3rd party libraries with version mismatches (i.e one dependency wanting one version and another wanting a different one). It's not some major gripe, just it has never been smooth sailing! :)
What I really like is the fact that you can basically build anything in this language. From command line tools over Apps or small GUIs up to full fledged Server Backends or Webservices, even WASM... everything is possible.
The NativeAOT approach is also very interesting making it possible to build native binaries similar in size and performance to languages like Rust and Go (not quite actually, but close).
It's also possible to build "single binary" tools by using <PublishSingleFile> which comes in handy when building small helper tools for the command line.
Yup! I recently took a pretty substantial project I wrote in 2006 in Java that was sitting in a tar file, unpacked it, and it ran just fine with a current JVM. Even better, I was able to compile it again with no problems: again, with a modern JDK. I wish I could say the same for years of projects written in Rust and Haskell: the Haskell ones are almost all bit rotten since I haven’t kept them up to date with GHC, and Rust is similar. Those two are even worse since with Java I had a rich standard library, so I didn’t have any 3rd party dependencies in my 19 year old project. The Haskell and Rust ones rely on Hackage and crates, and keeping things working for that long would require me to do bonus work beyond my actual project code. I’ve had similar but less painful problems in Python land: the library APIs are mostly stable: the biggest headache there are projects that predate python3 so there’s some work to bring them up to date. That’s at least a one time investment.
Java: no bonus work induced by third parties to keep projects alive, keeps working for a long time. Would recommend.
> I wish I could say the same for years of projects written in Rust and Haskell
Back in 2021 I ported a small C program I wrote into Rust as part of learning the language. Since I was inexperienced even though it's small and Unix specific I added about two dozen dependencies including transitively a Windows API dependency via somebody's terminal lib.
So, that's a 2018 Edition Rust program, untouched since November 2021.
The binary of course still runs just the same as ever, I've used it a few times over the intervening years - but we'll take that as read. Lets go into the source code and build it again today, how much work will it be to get Rust source code working years later with a brand new Rust toolchain and different OS?
It just works. Not like "Well, I had to run some updates and modernisations" it just works.
> the Haskell ones are almost all bit rotten since I haven’t kept them up to date with GHC
FWIW, over the last couple of years the stability story has got hugely better, thanks largely to the efforts of the Haskell Foundation Stability Working Group.
You can see the breakage inventories that I've produced for the last few GHC releases, and see that the amount of breaking changes is decreasing rapidly:
Between compile times and HLS feeling fragile in VSCode, I’m pretty much done with Haskell at this point. Very nice language, just not my thing anymore.
> Yup! I recently took a pretty substantial project I wrote in 2006 in Java that was sitting in a tar file, unpacked it, and it ran just fine with a current JVM. Even better, I was able to compile it again with no problems: again, with a modern JDK.
I've seen plenty of Java projects that don't work on anything more recent than JDK in the enterprise space (typically large Spring systems, not even Spring Boot, also DB drivers and pooling solutions seem to be quite brittle in that regard), though I will say more or less the same about old .NET codebases (before Core was a thing), old PHP, Node.js and so on.
Most of the time, it comes down to complex dependencies.
Stackage is mandatory for a “stable” Haskell env, even for simple/toy projects. It means you get predictable versions for GCH + hackage libs until you explicitly choose to upgrade.
this is definitly not true anymore, when the java libs used jaxb/xml/javaee stuff. most often because of java 9. its possible to make them running but its definitly not without issues.
I did run so many 10 years old java binaries it was NEVER without issues.
From what I gather, the only time this occurred was very early in the C#/.NET ecosystem (.NET2) when generics were added in November 2005. So it should be at 20 years this year.
Both languages are very impressive and benefit from the competition.
There were more breaking milestones, .NET to WinRT 8, WinRT 8 to UAP 8.1, UAP to UWP, UWP to WinUI 3/WinAppSDK,.NET Framework to .NET Core, Silverlight, XNA, Managed DirectX.
All of those are also part of .NET ecosystem.
Agree with the competition remark, hence why my toolbox has been .NET, Java, JavaScript ecosystems on the first drawer for decades now.
Possible. I know little more than what I can google about .NETs history; I wasn't around for it.
What I can say (MS hesitance aside) is that it is excellent for web applications where the ability to sustainably bear complexity of business logic is critical to business success.
I only really saw that concern in the java ecosystem, and I am very happy .NET exists, if for no other reason than to force java to get better. Many ancillary tools (source generators, xml code generation, integration of compliance metrics) that are only ever found in java are already present and even better in the .NET world.
Possibly. I'm a relatively recent comer to the c# ecosystem (2021ish). It's been good and avoids some of the warts of java.
Really, though, I'm very happy there is competition in the GC enterprise languages for linux. Regardless of who is "better", the competition will continue to drive progress in this area.
You can opt into most of them by setting LangVersion manually to your preferred C# version.
It works since most new C# features are just syntactic sugar which is lowered by the compiler.
Some of them require new types in the BCL (e.g. Range/Index, marker types for required/init/records), but for that you can just reference PolySharp which will generate the missing types on the fly.
Features that will not work typically also need runtime support, so default interface methods, static interfaces and the like will not work.
The number of times I’ve had to install an older version of Java just to compile some code is not even remotely funny to me. I really hate this idea that you can have code that just won’t compile if you are using a modern environment.
This is because Windows comes with some form of .NET, but also other programs end up needing to install multiple versions of the .NET runtime. Eventually, you just have them on your machine. It's the equivalent to installing every version of Python and just letting the problem sort itself out.
It's not different than other tech-stacks, you're just eating the costs up front instead of running into them in a more obvious manner.
.NET (in its entirety) has lots of breaking changes that won't work from one version to another. More recently MS has been better about documenting these, especially as .NET's footprint increases inside outside of the control of MS (non-Windows environments): https://learn.microsoft.com/en-us/dotnet/core/compatibility/...
>In fact, PowerShell itself is another reason I appreciate .NET it shares many concepts
PowerShell is built on .NET (in whatever form .NET Framework and .NET/core) lol. It doesn't "share" anything, it _IS_ shell for .NET.
I was excited about PowerShell at first but after doing a mid size project it, I don't like it anymore. It's such an odd language with too many quirks once you get serious. I think they would have been better off using C# syntax.
The syntax is barely the problem, the weird console rendering of objects behavior, the mixed object/text representation (since not everything buys into the objects), the breaking changes in the cross platform posh, the poor library support and requiring to load the world on importing modules... there's a lot of stuff powershell got wrong enough to avoid anything with it, and I have done plenty of serious things with it :)
I mean, there's really no justification for the Get-Help cmdlet. The -h flag has been universal for decades. If it were a replacement for 'man' it would be defensible, but not when most programs do not acknowledge -h
A few years ago an option to make self-contained builds was introduced, meaning you don't need any .NET runtime on your machine to run the self-contained app.
Yes, but in the case of Python, I feel it's a bit more nuanced. Simply having Python installed isn't enough—you also have to manage virtual environments (venv, Poetry, or whatever is popular at the moment). Personally, I find this to be more of an ongoing maintenance burden.
I do acknowledge that .NET has its share of breaking changes from time to time, but in my experience, the friction is significantly lower compared to other environments I’ve worked with.
> PowerShell is built on .NET (in whatever form .NET Framework and .NET/core) lol. It doesn't "share" anything, it _IS_ shell for .NET.
I never said it wasn’t! I was simply speaking from the perspective of the frontend experience. While PowerShell is built on .NET, my point was about how its functionality and design make it feel familiar to those already accustomed to .NET development.
>my point was about how its functionality and design make it feel familiar to those already accustomed to .NET development.
Because it's literally a "shell" into the .NET runtime/framework. PowerShell _extensively_ uses reflection capabilities.
My point was they're not sharing some design philosophy or converging, PowerShell is just exposing .NET functionality directly and in an interactive manner. You in fact, can write a pretty similar tool with a few lines of C# that makes use of dynamic compilation and reflection.
Otherwise, PowerShell shares nothing (and I mean nothing) with other .NET languages (C#, F#, etc). It's history and design choices come from things like KornShell and Perl.
Where do you think all those $variables and "-ne" operators came from?
Look, I’m not disagreeing with you here. I’m not even talking about the internal mechanics—I’m simply referring to the user experience. You're fixating on my choice of words and taking my point in a direction I never intended.
All I’m saying is that knowing .NET makes it easier to write PowerShell scripts, and I appreciate that. If that’s not your experience, that’s fine—but that doesn’t change my perspective.
> One thing I appreciate about C# and .NET is how well they resist codebase rot.
During the time I was working with .net from 2005-2020, I saw the transition from Webforms to ASP.NET MVC to the MVC/WebAPI split. I also saw the transition from Linq2SQL to Entity Framework.
There was also the weird time when you could run ASP.Net Core and EF Core on top of .Net Framework.
Then the entire .Net Framework to .Net Core was a major upheaval.
With .NET, this issue is much less pronounced. While occasional adjustments are necessary, the environment is largely self-contained, minimizing the overhead required to get things running. As long as the .NET SDK is installed, running dotnet restore is usually all it takes—even when moving the codebase to an entirely new machine.
Some third-party libraries evolve more rapidly than others, but the core .NET libraries remain remarkably stable. More often than not, you can transition between major versions without needing to modify any code.
If I were starting a long-term project that required ongoing maintenance, C# would be my top choice. For quick scripting needs, I’d lean toward Python or PowerShell. In fact, PowerShell itself is another reason I appreciate .NET—it shares many concepts, and knowing .NET makes it easier to understand PowerShell. Plus, since PowerShell can directly leverage .NET libraries, it offers powerful scripting capabilities. I was thrilled when PowerShell became cross-platform, much like .NET itself.