Would .NET 8 be a good challenger ? I previously didn't consider it because the compilation to binary was looking more like an experiment, and the example I've seen were quite verbose (in a java way).
Would .NET 8 be a good challenger ? I previously didn't consider it because the compilation to binary was looking more like an experiment, and the example I've seen were quite verbose (in a java way).
This was my first experience while getting started in the .NET ecosystem. I wanted something similar, I wanted to build small console tools/services and F# looked cool but hit the reflection issues too soon.
I mostly use crystal and golang, but both have their own issues. Hopefully F# improves with time to be fully usable with AOT!
Memory usage is important to me and golang is very good at that being light, but I really hate writing it for various personal reasons.
If I had more free-time I'd just simply go with Rust but you know, free time is limited :P.
[1] https://programming-language-benchmarks.vercel.app/csharp-vs...
Many tests there are at odds with the areas of optimizations that get most engineering effort investment in .NET: high level and/or application logic and high-performance primitives like Span, Vector, etc. (with the exception of perhaps Regex-Redux, but even there I'm not sure why the results are so low, because C# has one of the fastest[0] regex engines that only loses to Intel Hyperscan, Rust one and PCRE2).
Probably the best way to go about this is to just give it a try with a sample project and see if the RAM usage is to your liking - you can get far with plain 'dotnet new console --aot' and standard library (once you're done, .NET's variant of go/cargo build is 'dotnet publish -o {output folder}').
Overall, .NET tends to have higher memory footprint than Go because its GC is designed to sustain much higher allocation rate and heaps spiking to much higher use without severely throttling performance (which Go does). But there are interesting developments with the new GC mode called DATAS. I made a very simple example project some time ago to showcase .NET's concurrency and publishing experience to someone else which shows that it now rivals Go where it's the strongest[1].
[0] https://github.com/BurntSushi/rebar#summary-of-search-time-b...
It isn't exactly equivalent to the benchmark game's version. The biggest difference is that it doesn't permit parallelism.
For more details on the benchmark model: https://github.com/BurntSushi/rebar/blob/master/MODELS.md#re...
.NET does well overall in rebar's benchmarks, but less so in regex-redux (in both the benchmark game and in rebar's version of it). Not sure why. I haven't investigated. Of course, this is assuming you aren't using .NET's default interpreter engine. You've got to switch to the no-backtracking or compiled modes to get decent perf.
This is the benchmarks game:
https://benchmarksgame-team.pages.debian.net/benchmarksgame/...
.NET 6 was already capable of most things you are looking for, but there are some limitations. I personally think it is a really versatile language and if you know it, you can get the most things done somehow.
I wrote a little cross platform C# command line tool called `tone`[1] for tagging audio files and it compiles via github actions for windows(x64), linux(x64,arm64,arm6,arm7), macOS (x64, arm64) as a single monolitic binary (similar to `golang`), which is pretty cool.
With the right compiler flags it is not even too big (about 20MB, for comparison a `golang` binary with similar features would be about 5MB, `rust` more like 1MB or less). You can also go WASM (which is generally supported, but feels a bit experimental at times).
In the GUI department there are three main competitors:
- MAUI - Windows, macOS, Android, iOS (Microsoft's pet, xamarin successor)
- Avalonia UI - Windows, Linux, macOS, Android, iOS, WASM
- Uno Platform - Windows, Linux, macOS, Android, iOS, WASM
All these feel kind of unfinished, I like Avalonia UI the most, but it's lack of standard libraries for real world apps (Preferences, SecureStorage, Encryption Wrappers, Phone-Hardware-Access, Media-Players, WebView) and the outcoming App Size (>50MB) made me use Flutter for my personal projects (App size ~15MB for the same feature set). For some Apps it might be ok..NET may also still be incompatible / unfinished on other OS and platforms (e.g. RISC hardware or BSD operating systems). So if you only target the mainstream systems like x64 and the raspberry pi, it might not be a real problem.
I was thinking that flutter is a dart library/framework ? How is it compatible with C# ?
I think Flutter has a lot of advantages over the C# UI libraries and is worth learning when planning a Cross Platform UI or App.
It's possible with C#, but you have to work around a lot of shenannigans depending on the use case.
Command line apps are totally ok with C#...
JIT: dotnet publish -p:PublishSingleFile=true -p:PublishTrimmed=true
AOT: dotnet publish -p:PublishAot=true
Avalonia[0] and MAUI[1] have known working templates with it, but YMMV.
[0] https://github.com/lixinyang123/AvaloniaAOT / https://github.com/AvaloniaUI/Avalonia/
[1] https://github.com/dotnet/maui (try out with just <PublishAot>true</PublishAot> in csproj - it is known to work e.g. on iOS)
On the other hand, I would absolutely use verbose to describe both C# and Java. They are huge languages, with many features, a complex syntax, and conventions and patterns that lead to writing a lot of hard to understand code.
I'd use Go over both of them any day, especially when it comes to writing cross-platform GUI or console apps that can be quickly compiled and easily distributed.
Other options to consider might be Nim or Zig, but these are not as mature as Go.
I think those are quite innately related, yes. But I believe you also mix verbosity up in your very next sentence, for what it’s worth — readable, maintainable code is not as close a concept. In fact, certain type of verbosity helps readability, e.g. I argue that Go’s identifier capitalization harms readability, and marking it at a single place by public/private is much better, at a tiny price of more verbosity.
“Clever” code is another topic, there is definitely overly clever code, which is a net negative, but in this particular comparison, is a hand-written, 3-times nested for loop with any number of side effecting statements more clear to read than the “smart” stream/linq expression? I would argue the latter is much more readable and maintainable. For another, even better example there is that math proof, which can be done an order of magnitude faster by choosing a clever notation, but I can’t look up its name yet.
Re error handling, no, go doesn’t force you to handle the errors. It forces you to do some stupid meaningless if err ritual, that won’t result in correct handling of the error case, and will in fact often swallow errors. Java’s checked exception does force you to correctly handle it, though, but even runtime exceptions at least bubble up, making the default action (doing nothing) correct.