using var stream = GetStream(); does not introduce new (lexical) scope, avoiding use means that the type system either has to understand move semantics (in case the stream is returned or move elsewhere, but then, what about sharing?) or have full-blown borrow checker which will emit drop.
For me, personally, heavy use of the => operator (which happens to coinside with my main complaint of a lot JavaScript code and anonymous functions). You can avoid it, but is pretty standard.
Very specifically I also looking into JWT authentication in ASP.NET Core and found the whole thing really tricky to wrap my head around. That's more of a library, but I think many of the usage examples ends up being a bunch of spaghetti code.
You'll see forms of it in practically every (good) modern language. How on Earth is it confusing?
Authentication is generally a difficult subject, it is a weaker(-ish) aspect of (otherwise top of the line) ASP.NET Core. But it has exactly zero to do with C#.
Same here. And I’m not aware of quality issues with GxHash either. For large(r) inputs I’d expect it to be easily competitive. And it’s better than XXH3 on my M4.
If whatever you are doing is heavy on hashmap lookups (and you are ok with not rewriting into something more bespoke+complicated) - the faster hash function and the cheaper baseline cost of calling it - the better (i.e. XXH3 can have disadvantages, with its popular impl. for dispatching to the necessary routine).
This looks like an interesting potential alternative to GxHash. GxHash is nice but sadly I found AES intrinsics to have somewhat high latency on AMD's Zen 2/3 cores, making it a loss on short strings (but until I measured it on our server hw, M4 Max sure had me fooled, it has way better latency despite retiring more AES operations!).
I don't know, all I know is that in my experience some HN commenters don't remove the `.m` from their Wikipedia links. Probably because that's inconvenient to do on mobile devices.
Quite a few languages "loved" by "Linux communities" tend to have rather rudimentary integration with Linux kernel's facilities or worse packaging story.
For example, Go does not understand cgroups limits and needs an external package to solve this. .NET can read and accommodate those natively. It also ships with excellent epoll-based socket engine implementation. It's on par with Go (although I'm not sure which one is better, but .NET performs really well on high-throughput workloads).
IIRC all previous conversations about checked exceptions here ended up with the swift conclusion that they are heavily discouraged throughout Java code.
And more. I'm not sure what you found in (checked) exceptions. If you'd like explicit error handling, we have holy grail in the form of Rust which beautifully solves it with implicit returns, error type conversions and disambiguation between error and panic model. I'd prefer to use that one as it actually reduces boilerplate and improves correctness, the opposite to the outcome of using checked exceptions.
None of those arguments are convincing. In many cases, you can't handle errors more reasonably than just crashing or telling the user something went wrong. Java has RuntimeExceptions, which do not have to be declared in the function signature. Division by zero, or trying to index an array out of bounds, and the dreaded NullPointerException, are some examples of RuntimeExceptions.
You usually wouldn’t crash the entire application, the request that causes the issue will return a 500 error. (Or equivalents for non-web environments.)
Some exceptions are not recoverable and may cause 500 error. Others such as FileNotFound are recoverable, for example by reading the file from an alternate location.
> I'd prefer to use that one as it actually reduces boilerplate and improves correctness, the opposite to the outcome of using checked exceptions.
Reducing boilerplate is not a valuable goal in and of itself. The question is, does the boilerplate buy you something? I think that with checked exceptions it does. Having an explicit type signature for what errors a function can raise improves correctness a great deal because the compiler can enforce the contracts of those functions.
I agree that the Rust approach is good too, though I don't agree it has any strong advantages over the way Java does things. Both approaches are equally respectable in my view.
In the end, .NET is going hybrid route. Circa .NET 10/11 Roslyn will stop emitting state machines and something state-machine-like will be produced by the compiler itself iff the asynchronous execution suspends, and will be otherwise practically free.
Mind you, short-lived operations are much cheaper with stackless co-routine model like in C#/F# or Rust than spawning an entire, even if virtual, thread/process.
I get why they went the async route due to performance implications and such, just like the old cooperative multi-tasking days everything was much lighter weight but one misbehaved process not yielding can block the whole OS.
Nice to see further improvement coming along in .Net however I conceptually prefer the everything is a lightweight process model to this function coloring async virus that invades the codebase now days, wouldn't be so bad if it had been easy to do sync over async from the beginning without caveat in .Net so you didn't need to have dual sync and async api all the way down the stack.
Usually dual APIs are offered when they do distinctly different things. Async calls on Socket go through epoll/kqueue via SocketAsyncEngine, which has observably different behavior to regular sockets. There is no such duality in high-level APIs like HttpClient's `.GetStringAsync`.
You are not free from having to worry about it with virtual threads either. If you block a carrier thread with such a low-level API call, the runtime will have a bad time. Or you will always end up paying for a context switch (if you maintain a separate pool of block-able threads).
Green threading UX is better for "regular" code that never bothers to take advantage of concurrency features, but if you do want them, you are quickly back to usually more ceremonious structured concurrency abstractions which, lo and behold, can reimplement the same task system with a worker pool but on top of virtual threads.
If you start to care about cancellation, suddenly you are back to coloring problem regardless. I agree with you that having to write many await's in quick succession is tiresome and unnecessary. It's partially a fault of library authors who name methods "GetSomeLongNameAsync" instead of "Get" or "Query". But other than this it's not as invasive as people make it out to be, and encourages writing highly concurrent code - reducing latency 2x can require moving one or two awaits around. Not so much in Java/Erlang/Go.
I haven't found this is the case many times, many api will have two versions of the api with XxxAsync versions all the way down, maybe less so now days but it took a while to get async entry points added everywhere so you could use it properly, such as ActionResult.ExecuteResultAsync and IAsyncEnumerable as a couple examples.
I suppose the difference of opinion comes down to whether you consider hiding side effects a good or a bad thing. And whether you want to have easy composition and cancellation (Go struggles with passing context around a lot, in .NET it's much less of an issue if at all, depending on codebase).
If you don't want to join on some other virtual thread or goroutine completing immediately (and with Goroutines it's additionally painful since you need to communicate completion separately), it's more difficult and costlier than doing so with tasks/futures.
CancellationTokens can be passed in synchronous functions just fine, I have done cancellable sync apis before cancellation tokens existed usually its a .Cancel() on the thing doing the work just like Command.Cancel() in the Sql client or Connection.Cancel() in a network client. I agree CancellationTokens are better and always use them now and thats not the problem with async.
The problem is the need to color functions with async and if you have existing client code that call existing synchronous methods it not easy to move their internal implementations to async form so that you can remain backward compatible without copy/pasting the same layers of code with different function coloring to async.
For those interested as to why: https://news.ycombinator.com/item?id=43396171
A few more arguments while we're at it:
https://dotnet.microsoft.com/en-us/platform/telemetry (Linux leads with 77% of all systems invoking .NET CLI commands)
https://github.com/dotnet/runtime/blob/main/src/libraries/Sy... (first-class epoll/kqueue integration with async, much like the one Go has with goroutines via netpoll)
https://github.com/dotnet/runtime/blob/main/src/coreclr/gc/u... (GC implementation is cgroups-aware, unlike Go)