Bflat: C# as you know it but with Go-like tooling
github.com
github.com
Have been writing C# to interact with C/C++ and publishing C ABIs as static/shared libs that are natively compiled
My mind has been absolutely blown with what modern .NET and C# are capable of doing in terms of low level/systems program and interop with C/C++/Rust etc.
The performance and object sizes are killer too.
I think most people don't know or think C#/.NET are capable of this
Can envision a not so distant future where C# is a common choice for places when you'd typically reach for C++
Also, the folks on the .NET Interop team are all super friendly and willing to have a conversation with you or answer questions. My experiences with the whole .NET organization at MS as a random person has been nothing short of shockingly pleasant.
Since dotnet Core 3, you can use assembly trimming to remove unused assemblies. That results in a package of around 10MB for a Hello World app, or more like 40-70MB for large, real-world apps.
From dotnet 5 there is also member trimming, which will trim unused parts of assemblies, which will further reduce the size. I haven't used this yet, but Microsoft claim it can result in packages 5x smaller than with assembly trimming, e.g. only 2MB for a Hello World app.
There is also AOT compilation, but I wouldn't hold my breath on seeing that become production-ready any time soon (Microsoft have been hyping it and saying it's "coming soon" for 10 years or so).
I also have a Rust version of the project. 710 lines of Rust[0], 128 total dependencies in the tree, building in release mode with the MSVC Windows compiler. Final size of the binary is 2.29 MB, build time of 22.2[1] seconds.
Things are not great when your build times rival Rust's, and the output is slower and an order of magnitude bigger.
[0] Note that the C# version does have more robust handling when writing its output file than the Rust version, which adds couple dozen lines. Also the style conventions for brackets puts opening brackets on a new line for C#, the same line for Rust.
[1] Measured with hyperfine configured to run "dotnet clean -c Release" and "cargo clean" before each run.
Why would you exclude those in this comparison - they're already (guaranteed to be) installed on your windows targets?
How about linux/Mac targets?
I think 20-30MB is quite good - puts it in the ballbark of golang.
2MB+ for rust actually sounds a bit big -that's stripped?
> Why would you exclude those in this comparison - they're already (guaranteed to be) installed on your windows targets?
Note that this is a stand-alone build; it doesn't require the runtime to be installed. With that in mind, you're right they should be included, which would increase the build size by 8.3 MB.
> How about linux/Mac targets?
I can't build a Mac target because I don't have a Mac. I just built for a linux-x64 target in WSL, and the resulting binary is 35.0 MB. The Linux build looks like it's packaged the CLR into the main binary instead of keeping them separate, which would account for the greater size.
I did do a benchmark with hyperfine, which gave a 25.5 second build time. However, this is on WSL1 building off and on to an NTFS drive, which has known performance issues.
> I think 20-30MB is quite good - puts it in the ballbark of golang.
I've never used Go, but my understanding is that the Go compiler is very fast but doesn't do as much in the way of optimizations. If that's the case, having a larger and slower binary compared to Rust would be expected before you get to the packaged runtime.
The issue I'm taking here is that doing a trimmed dotnet build is (in this case) giving the same build time as Rust, but is only doing some AoT compilation and dead-code elimination. Rust is already doing that in addition to a whole host of other optimizations.
From a user perspective, this feels like dotnet is giving me a worse end product for the same time taken. Especially given the Rust version wasn't harder to write than the C# version (in fact, due to bad documentation the C# version was harder).
> 2MB+ for rust actually sounds a bit big -that's stripped?
No, that is not stripped, and with the standard release profile.
But Rust is such a very different beast than dotnet, that I'm unconvinced it's a useful comparison; IMO a better comparison would be Golang.
Just took a look at my current project, which has several components: an ASP.NET web UI is 80MB, an ASP.NET API is 65MB, and backend services range from 40-55MB (these are all pretty complex, production-grade components).
It’s a tarball. Unpack it wherever you like.
What exact problems did you have?
Edit: I’ve even “installed” the .NET SDK on ARM/Aarch64 devices this way. Zero issues.
Welcome to Linux?? Not to be sarcastic but if you want your hand held install Windows for your .Net development. It's pretty nice over there.
Maybe more like, "Welcome to MS tools on Linux?" There are no similar issues with installing a JDK, for example.
I think that’s a pretty far fetched complaint. There are tons of software out there on Linux which will break if you don’t satisfy their dependencies.
I’m sure the OpenJDK-tarball has some system-wide dependencies too (libssl?), but you can’t tell that because you probably installed it as root, using a package-manager instead.
If you do the same with the .NET SDK (use root, install via package-manager) you will find everything working equally smooth.
The Ubuntu repos suggests there are more dependencies than just plain libc.
https://packages.ubuntu.com/hirsute/openjdk-11-jre
Could it be you have those dependencies satisfied through other things you’ve already installed?
> Do you have a reference to your claim that Java requires libssl?
None at all. It was an example of something I found it reasonable it might depend on, since .NET also depends on that on Linux :)
However, I often keep a collection of older versions and different patch levels in my home directory. These work fine for testing with the non-openjdk distributions for compatibility purposes.
I wasn't familiar with the icu library issue, so maybe it is something straightforward, but it seems odd that the fix was an env var. I certainly wouldn't say something like "welcome to linux" because of a scenario like this.
And they are obviously going to work because you’ve satisfied all the main OpenJDK dependencies through the install with your package-manager.
If you repeat your own scenario with the .NET SDK instead, you will have the exact same experience.
Its how I did it before the distribution packaged OpenJDK, which really wasn't that long ago.
I chiefly like asdf because I typically need at least two toolchains (with various versions for various projects) - eg ruby and nodejs, or python and nodejs.
> I think most people don't know or think C#/.NET are capable of this
Take all of this amazing stuff and it also works on embedded/raspi4... I have been playing around with using C#8 to directly drive & sample GPIO. Who needs timer ICs when you have a busywait while loop checking the high res timer...
Also, don't forget that you can go open an issue or submit a PR to any of the major .NET repositories right now, and expect to have your work (assuming accepted) incorporated into an official .NET release within a year or so.
And tooling, etc. Check out visual studio 2022. Its available in preview now.
A lot of people are concerned about power usage these days, particularly if these things are running off a solar cell.
And these days, most embedded controllers include some kind of timer anyway. Micropython has a timer interface that interrupts into a python subroutine. I use this for application level routines interfacing with a hardware watchdog.
If you're running off a battery say, then it's better to build your software from the start to optimize for the various sleep modes.
https://lastminuteengineers.com/esp32-sleep-modes-power-cons...
Yes! They also publish videos of their design review discussions - I submitted a cryptography-related PR a while back, and it was really cool to watch my proposal being discussed, and then even cooler when my code made it into dotnet :)
> And tooling, etc. Check out visual studio 2022
Don't forget JetBrains Rider - I switched from VS a few years ago, and haven't looked back. VS is great too, but in terms of performance and stability, Rider kicks it to the curb (IMO).
However, the build/package system for this is still a complete mess if you want to target more than one architecture; I've spent much of the week looking at the question of how to make cross-platform assembly A depend on platform-specific assembly B, where B is one of B-win or B-mac, and it seems to require carefully hand building B into a nuget package.
I'm coming to appreciate msbuild, though. Or maybe that's Stockholm syndrome.
I think making it open source has come with a cultural change that's still propagating. It means not just defining the "Microsoft way" to do things but coping with myriad use cases turning up in the issue tracker.
Using XML as a general purpose programming language is also very ick.
It gives you the same IDE experience for your build scripts and your code including REPL for experiments and a debugger when needed.
since it is .NET Core they are as cross platform as your other code.
I think the big downside is that the industry still thinks of .NET as stuck in .NET 2.0 or something, from my casual browsing that .NET is a skill not C#. Regardless, I'm getting kind of excited for .NET 6 on official release, and doing the migration of all our apps off framework to the latest and getting some getting the new lang version.
If it is the former I can say that I never ever built on top of Sitecore or SharePoint. Recently only Asp.NET Core or whatever it is called now.
Actually it was already there in J++, and now we have Oracle trying to add back what Sun killed in 2000, with keeping 26 years of history running, it is ironic how some things turn around.
Scott Hanselman has a couple of guides on his blog on how to get it up and running.
The on-by-default telemetry and license restrictions come to mind
https://github.com/VSCodium/vscodium
It is a repository of scripts to automatically build Microsoft's 'vscode' repository into freely-licensed binaries with a community-driven default configuration.
I didn’t know this until recently when someone pointed it out.
https://github.com/dotnet/core/issues/505
Thought it was relevant since OP is talking about a Linux IDE for C#
https://github.com/MichalStrehovsky/zerosharp
I did a survey recently of binary sizes for .NET apps and comparisons to other languages. Things like NativeAOT (on which Bflat is built) and Graal Native Image let these languages get down to a binary size , startup speed, and deployment model similar that enjoyed by Go and Rust developers.
Which, according to HN/proggit, is the only valid measure of a programming language. :)
The trouble I had last time I tried (.NET Core 3.1 I think) is you needed a cross compiling versio of RyuJIT that has the same bitness of your target. That is , you needed one that ran on linux x86 targeting linux arm32. And that was not easy to find. Maybe if I try compiling from a Arm32 host it will be easier.
D better C mode is getting better with each version actually, even if there are some corners to fix.
[1] - https://en.wikipedia.org/wiki/Managed_Extensions_for_C%2B%2B
I also hope you keep working on D(betterC) but for now I stick with C, generating C using bb(clojure) is also an option.
> I'm not ready for people to see (or to accept pull requests) things that are specific to bflat. If you think bflat is useful, you can leave me a tip in my tip jar and include your GitHub user name in a note so that I can give you access to a private repo when I'm ready.
It's not hard to use CoreRT directly. [1]
[1] - https://github.com/dotnet/corert/tree/master/samples/HelloWo...
Edit: Actually B♭ minor is the enharmonic equivalent of A♯ minor. IE another case of things in music that are the same but aren't.
slowly backs away
And now I'm down the rabbit hole of reading about tuning systems again.
If you want C# and G (a nasty tritone) together, then you need something else. Adding in a Bb will give a nice diminished chord.
hmm?
edit: nvm, it seems he's MS employee, so it's I guess it's legit.
don't care about pedigree - no source, no trust for a compiler...
- Can bflat be used to compile F# code?
- How do you build multiple files?
The official `dotnet` command is not to my taste for a few reasons. It uses XML, and it is quite slow, e.g. a simple "Hello, world" project takes 2 seconds to launch every time. I mean, it always takes 2 seconds even after compiling everything prior to that. It might be acceptable for an interactive development environment that employes an auto-compiling workflow, but for a CLI tool, it is too much of a burden. I know Microsoft are trying to improve it, but at least up until now it hasn't been very successful.[1]
On the other hand you have a point that "dotnet" is trying a bit too hard to be a magic swiss army knife.
https://docs.microsoft.com/en-us/dotnet/core/deploying/trim-...
dotnet publish -r win-x64 -p:PublishSingleFile=true ---self-contained=false
dotnet publish -r linux-x64 -p:PublishSingleFile=true -p:PublishTrimmed=true --self-contained=true
To give an example of this for a reasonably complex test tool I have on .NET core 3.1, the Windows exe is 3.7MB and the linux binary is 38MB. I'm guessing there's some room for optimization in the process though, as the linux binary is compressed (tgz) to 13.37MB.38MB is a pretty typical size for a real-world, self-contained, assembly-trimmed package, and the size comes from the runtime itself, plus the core assemblies that weren't trimmed out.
-p:Configuration=Release -p:DebuggerSupport=false
FWIW, I did also try the following, but found they had basically no impact on output size: -p:TrimMode=link
-p:EnableUnsafeBinaryFormatterSerialization=false
-p:EnableUnsafeUTF7Encoding=false
-p:EventSourceSupport=false
-p:HttpActivityPropagationSupport=false
(Tested on .NET Core 3.1.5)I've been enjoying the way that .NET has been evolving in pragmatic ways. The initial implementation basically created a self-extracting zip that would include the runtime. That had its drawbacks, but it was a way for them to get self-contained deployable out the door with minimal hassle. Sure, it meant taking up a bit more space, but it worked and solved what most people cared about: having a single file that they could run without needing to install things in the OS.
Likewise, they came up with ReadyToRun. Basically, they'd AOT-compile stuff for fast startup times, but include the byte code so that things could be JIT-compiled during runtime. This meant that the AOT-compiler didn't need to be perfect and that they didn't need to worry too much about things like the performance of reflection code. That code would end up JIT-compiled in long-running programs. Again, a pragmatic approach that does have some drawbacks (like large deployable artifacts), but they got it out the door and have been improving it as time goes forward.
A more pure approach might be to wait until one can produce a really top-notch AOT compiler, wait until one can replace certain reflection-heavy code, wait until one can optimize libraries, wait until one can do lots of testing to make sure you don't have regressions, etc. But that requires a lot of time while what a lot of people might want isn't a pure solution, but just something that allows them to speed up start times.
Likewise, zipping up the runtime with your code into a self-extracting and self-running file isn't the most pure approach, but it meant that you could get a single file to scp and just do `./myprogram` on.
If you include extra DLL or .so files, those still have to be extracted so that the operating system dynamic linker can load them.
Microsoft could have waited until .NET 5/6 to offer self-contained executables "the right way", but they were able to create something that offered 90% of people what they wanted a few years earlier.
The description of bflat is what you are looking for, and it's the second section of the readme.
bflat implements a form of ahead-of-time compilation.
This is closer to .net native conceptually, but that was only a UWP abomination.
edit: replies have pointed out this is actually closer to ReadyToRun, a neat feature I was not aware of.
it runs few tier for JIT, it still ship with IL and the JIT
don't advertise ReadyToRun as "hey we got AOT at home, says Microsoft salesman"
because all it does is makes me want to use Go instead, it feels and sounds bloaty
Also, to build that exe you have to use the .NET SDK which pulls in lots of tooling: MSBuild, NuGet, etc... It looks like bflat ditches all of that.
.NET Core will create a self-contained executable which can have AOT compilation (or not), but which will include the byte code so that it can be JIT-optimized at runtime.
This is about creating a binary that is small and uses some of the upcoming experimental stuff like Crossgen 2 and NativeAOT. Some of the Crossgen 2 stuff will land with .NET 6 this fall.
As the project says, it's about bringing together two components that are being actively worked on in the .NET ecosystem to create a compiler and runtime for small binaries.
For most people, you'll want the normal .NET self-contained Ready2Run binaries. They're compatible with everything and rock-solid. But sometimes you want to play around with something - like creating C# programs that are going to be tiny.
Microsoft and others in the .NET ecosystem are improving C#/.NET at a rapid pace and it's great. bflat is, as it notes, using what is being created in that ecosystem. I mean, bflat literally labels itself "Initial proof-of-concept release" at this point. The guy writing it is on the .NET Runtime team at Microsoft and is really interested in these types of things. I think we can all imagine ourselves creating a project that does things a bit differently to figure out what is possible, figure out possible future directions we could take our work, etc.
So, it is different from what is available in .NET today. It's written by one of the people on the .NET Runtime team who is interested in this stuff. Some of the concepts might show up in .NET 7/8/9. Heck, Crossgen 2 should be showing up in .NET 6.
It's a cool proof of concept of slimming down C# binaries and even the readme shows how things like stack trace information takes up space.
.NET Core was the name for the cross-platform version, but that's the default now and will be the future. No need to differentiate from the older Full Framework anymore.
I really hope some day we finally land it. Even as a full time Linux-user these days, BSD still has a special place in my heart.
Were you using Ionide?
The name is a bit of a blunder:
1. Because of the placement of the ♭ in ♭Flat, that's actually read as "FlatFlat".
2. The note D♭ is the same as the note C♯.
Well, actually...
Please, help me correct my prejudices :)
C# is a heavily OO language with powerful semantics. If you like Java but hate the JVM, C# is your friend. C# has traditionally had much better developer aesthetics than Java but that gap has closed some.
Also worth noting the Java licensing has gone batshit insane in the last version or two.
The problem is that there are always those that rather go with CentOS.
F# :)
Seriously though, I think regardless which flavor you use .NET Core is pretty good. You can work on whatever platform you like and deploy to any platform you like. There is usually at least one good library for the most common tasks (http, database access, cloud, big data) you might encounter while working as a software engineer.
> but Microsoft's software is known for being buggier than one would expect
I am not sure about this. Microsoft's software is used a lot more than anything else. They invested in software quality and FOSS a lot since the Ballmer era. I am generally pretty happy with the quality of MS software I use (.NET Core, VS Code, F#).
Having grown up with C, then C++ I find C# as the best compromise: expressive language, garbage collection, good performance, non-fussy syntax. When C# first showed up it was painful because for every other thing you had to call out to native Win32 libraries but nowadays I almost never find myself doing that.
Over the years the team added new language/runtime features at just about the right time: tasks, async, dynamic, reasonably tasteful collections.
For me Visual Studio Enterprise is a big part of it as well. I like plenty of open-source alternatives but honestly VS is where it's at.
For example, I always found "edit and continue" really flakey in VS - it was really slow, sometimes using it resulted in a long hang or an outright crash, and quite often the IDE wouldn't even give me the option to use it. Rider is rock-solid by comparison - I'd say VS (with ReSharper) and Rider are roughly at feature parity, but Rider kicks VS's arse on stability and performance.
Another thing I'd add is that all of Microsoft's UserVoice-type feedback sites are an absolute joke - you might as well be piping your ideas into `/dev/null`. I feel like JetBrains actually listens much more to what developers are asking for.
Huge fan of Rider, and actually JetBrains the company too.
it allows you to evaluate expressions at fly
it allows you to back in time (move e.g 2 LoC above)
it allows you to use the Immediate window to debug and evaluate expressions, execute statements, and print variable values. The Immediate window evaluates expressions by building and using the currently selected project.
We could start with the one that MS code is notably buggy :)
As far as I know most of the bread-and-butter consumer visible stuff is still mostly c++ (e.g. office suite, windows, etc.). I imagine there is a bunch of C# in Azure etc.
I could easily be wrong, been a while since I've spent much time with anyone working there. But these things have momentum and clean rewrites usually fail.
All of those are mostly ok, but we encounter reliability issues on a more frequent basis than software from other vendors, like Amazon and Google.
I've been a .NET Dev for 20 years. C# keeps trucking along adding features at neck-breaking pace. That can be good and bad. Personally I wish F# had more resources assigned to it at MS. Having said that C# seems to be getting more and more F# features as time goes on.
I did a small amount of Java in my career, and learned golang on my own time. Neither clicked with me or swayed me to consider a move to full-time employment using those langs. I've been learning Rust most recently and I'm considering looking for a job doing Rust.
This absolutely. Or that they had avoided the usual NIH MS is prone to, and just supported another ML variant (thus reducing the load to match the resourcing).
- very active language development, modern functional features - very strong standard library. I used to take this for granted, but over the years I realised many other languages and are nowhere near where .NET is - exceptional IDE. VS has no competition
True. Rider comes close, but it's no VS
Interested to know what features or characteristics you feel are absent or lacking in Rider?
About 6 months ago I had a side project where I took a C++ library and decided I'd try to translate it into every language that supports C/C++ Interop, to have a canonical "C Interop reference + comparison" repo for anyone interested
I found out that C# could do this, and started looking into how.
Long story short, it's now possible to use C# and .NET to directly interop with C/C++. Function Pointers, structs and all. You can publish a binary or static/dynamic library for any platform that's natively compiled -- zero dependencies.
It allows you to manually allocate memory and provide allocation strategies. Shit, you can even turn the GC off entirely (at this point the language is very barebones).
See ZeroSharp by same author:
https://github.com/MichalStrehovsky/zerosharp
So on top of this surprising viability for fairly low-level or native programming, it's also:
- Just generally good at everything/bad at nothing
- Blazingly performant, and getting faster consistently. Both at a language/computation level, and for things like web servers. ASP .NET Core Kestrel webserver has throughput only topped by a handful of Rust/C++ libs, and most recent preview included a new functional router API that increased throughout by +100,000rps.
- C# as a language is evolving rapidly and has already become a solid multi paradigm lang. Adopting FP functional features like pattern matching and lambdas. It has LINQ. It's actually pleasant to write now and doesn't always feel like verbose enterprise garbage. (I prefer modeling entities as classes/structs + using pure functions for working with them)
- The tooling and ecosystem of C# and .NET are rivaled only by the JVM. The developer experience and quality/depth of libraries available are fantastic.
There's more but that's off the top of my head.
Needless to say the last few months visiting C# and .NET land have changed my former opinion.
Note that this has always been possible - good native interop has been one the design goals from day 1. But recent features have definitely made native interop much nicer.
For me, it basically has all the advantages of Kotlin over Java. ASP.NET is also a lot better than any Java web framework I've tried. It doesn't really have new concepts, but everything works together without spending time glueing things together. Things just build and run with minimal hassle. Rider and Visual Studio offer excellent tooling that doesn't stop at odd boundaries (think about how most template engines have poor IDE support in the Java world).
With Java, how do you create a data class? Are you making Java Beans (and hoping no one ever makes a mistake)? Are you using a library like Immutables to generate code at compile time? Are you using Kotlin for that and compiling two languages? Are you using the records feature which just landed (out of preview) three months ago and doesn't work the way Java Beans work? Are you using Lombok and installing IDE plugins and doing fun runtime crazy?
C# isn't perfect, but it has a lot of the modern things that a lot of people want that are available in languages like Kotlin. The tooling is first-class and the libraries from Microsoft work well.
.NET offers AOT-compilation that doesn't involve a lot of trade-offs (mostly just binary size which isn't that important to most people). GraalVM is really cool, but also changes the performance characteristics of a lot of Java code and requires the community to think about re-orienting how they write Java programs.
Go is a great language, but many people want more features than the language offers and that isn't likely to change.
> I haven't seen that many projects written in C# that really impress me (like Java or Go excel at)
If you're talking about libraries, it's likely that because you're not a C# dev you aren't looking at C# libraries. If you're saying, "well, I see Kubernetes in Go and Kafka in Scala/JVM, but I don't see any equivalent in C#/.NET," then yes: there are fewer large open source projects in C#/.NET. If I were writing your comment, I would have said, "I see fewer influential open source projects" rather than "projects that really impress me". You're probably not impressed by Kubernetes so much as you note that it is large and influential.
I think C#'s lack of representation here comes down to timing. .NET Core (the first cross-platform .NET) is only 5 years old. At the time, we didn't know whether Microsoft was really committed to .NET Core or if it was just an experiment. By contrast, Kafka is 10 years old and Kubernetes is 7 years old. Both of those influential projects literally couldn't have gone with C# and .NET because they started well before cross-platform .NET really existed (beyond the unofficial Mono effort which didn't offer the same performance or sanction from Microsoft).
If you're coming from the open-source, Linux-deploying side of the world, C# hasn't been an option very long. I would say that it started becoming clear 3 years ago that .NET Core was truly going to be the future for Microsoft.
How many influential open-source projects do you know of that started in the past 3 years? Probably very few.
Realistically, it will take a while for a lot of people coming from the Linux-deploying world to see C#/.NET as a viable ecosystem. It will continue to be viewed suspiciously by some people for a while. If you're looking for influential projects, they don't come along frequently. Hadoop, Spark, Kubernetes, Kafka, etc. are the kinds of things that you don't see every year.
I don't think it's a reflection on the language so much as a reflection on timing and culture. I think C# is still thought of as the Microsoft-only, Windows-centric ecosystem that it used to be. I think people looking to create an influential project know that the broader community will accept projects written in Go, but it's unclear whether the broader community will accept projects written in C# - many people might just be turned off due to their preconceptions. So when you start the next Hadoop, Spark, Kubernetes, or Kafka, do you choose C# and potentially alienate part of the community who write off your project due to preconceptions about the language?
Plus, there's a certain amount of inertia around some areas. Data science and ML are still heavily Python-based. It's not that Python is the best language for those things, but the community is familiar with it and so if you're creating a tool for that community you're going to make it in Python. If you make it in Go or Java, it will just languish without usage and without people improving it. Is that because Python is a better language for impressive data science and ML projects than Go or Java? I think it's more around community knowledge and perception (and the already built tools they might be familiar with and also want to use).
> Also, and maybe this is unfair, but Microsoft's software is known for being buggier than one would expect and I imagine that C# is used a lot there
Yea, that is just unfair. I've found C# to be so easy and seamless. No more headaches around builds, no more headaches about how to glue together Maven generating X while Hibernate expects Y while something else expects Z. I think part of it is that because C# was a Microsoft project for so long, the ecosystem didn't end up with as many camps in it. With Java there was Sun, IBM, and RedHat all kinda pushing similar yet slightly-distinct stuff. I think Java also fell into a problem where so many people tried to solve the "I just need a data class" problem that now we have a bunch of solutions that all act slightly differently and can lead to headaches.
Realistically, this assertion isn't disprovable. "Microsoft software is known for being buggier": is it? As someone who truly hated Windows for a long time, I would definitely have been on that train a while ago. Is their software today of worse quality? Realistically, I don't use Microsoft software much and never really have. I don't really think it's worth addressing this more than I already have since it wasn't really a fair criticism to begin with based on a potentially spurious premise.
1. The seamless integration to things like containers (working with Docker Desktop is fantastic - and you can debug your code inside the container).
2. Razor pages. I gave up on hideously complicated SPA and use Razor now. The user experience is similar but it's a lot more secure generating everything on the server.
3. Deploy to AWS ECS or AWS Lambda with a few clicks. You need the AWS tools installed in Visual Studio but as a one man shop this is insanely productive.
4. Write it on Windows, deploy it on anything. The two use cases I use the most are things like Linux based containers but also ancient Windows servers in client environments where the infrastructure guys don't want to install new libraries. I wrote a small web slurping utility that had to be deployed on an old Windows Server 2012 machine and the self contained executable just worked without having to install anything else.
.NET Core has been fantastic for me.
Especially tooling, people might like it or not, but I think MS has really strong people working on languages and combining compilers and tools, so you have things like editing code while debugging it (at fly), evaluating expressions at fly, IDEs that makes you use refactor often and make your life waay easier and those are only things that I notice the most
Everything from the fantastic IDE and tooling, to the massive and comprehensive standard library, to the wide range of outputs (CLIs, websites, APIs, mobile apps, games, native desktop apps), to the cutting-edge projects like Blazor (first component-based UI framework not in JS that can be run client or server-side) means you can build whatever you want without much overhead. Even language and framework features like LINQ are unmatched.
If you want a single word, I'd say it comes down to pure productivity.
Microsoft is sitting on a gold mine and they don't know it!! yet!
C# has always been a good systems programming language. NET Core/5/6+ have just taken that to a new dimension with x-platform and better tooling.
The best thing about the MS stack is that it is built for the 8000lb gorilla projects (I.e. their own internal stuff). If you have a unicorn solution that has 2000 projects and requires 36 hours to build, visual studio, msbuild (dotnet build) are the things you want to be relying on to get you through the day.
Sometimes things get posted to HN as if they were "you should use this because it's the future" rather than "this is a cool thing I made to show what could be possible".
In the author's own words:
"I'm Michal, I live in Slovakia, and I work remotely at the .NET Runtime team at Microsoft.
In my spare time I work on C#-related side projects that I find fun but don't particularly overlap with my day job. You might know me from my greatest hits such as "Let's make C# run on Windows 3.11!", "How about a snake game in C# running on DOS?". I also write articles such as the one on how I built a fully self-contained game in C# in 8 kilobytes."
Yup. There's really not much extra code in bflat compared to what's in the dotnet/runtimelab repo (in the NativeAOT branch). This just packages things differently so that one doesn't need the .NET SDK (plus Windows SDK if targeting Windows). The 100 MB bflat ZIP is all that's needed to target Windows or Linux.
The author is perfectly within their rights to keep it private, and we are perfectly within ours to call it out.