> Top-level statements enable a script-like experience for experimentation similar to what Jupyter notebooks provide. Top-level statements are great for small console programs and utilities.
This is great for small, one-off scripts that can handle simple tasks for sysadmin work. I use Powershell for handling configuration changes on the CLI, but I don't write and save many scripts with it. Perhaps I need to learn more about the PS environment to fix that. Either way, I have a hunch that there are some tasks—which would be cumbersome in PS—that this new feature would make accessible.
Wow, function pointers is huge for native binding. Lot's of QOL new features as well. C# and .NET framework (core and future merged .NET) in general keeps delivering. Love the entire stack;
Init only setters are a dream come true. Property initializer syntax to me is very readable and lack of read-only support after initialization was the main reason i avoided using it
I get the impression that Microsoft is dogfooding C# on a greater level than before beginning with Span<T> and Memory<T> in .NET Core 2.1 (among others), still clearly ongoing here in C# 9. It's almost like a paradigm shift where I note the .NET Framework of past focused on higher level features and evolving the standard library first and foremost. I'm not sure if it's just me though, or if not, what the reason behind this push actually is.
And from the experience with Midori as well, which got them first in System C# (M#), which also contributed to span and string_view papers for similar capabilities in C++.
The bigger win I think for the `not` patterns will be anywhere you remove constructions in the form:
if (!(e is Class)) {/*...*/}
Sometimes the ! gets visually lost in the extra parentheses. The `not` patterns should especially make it cleaner to write certain styles of DeMorgan substitutions (!a && !b to !(a || b) type things) in ways that will be easier to read.
Given those big wins, they alone provide a useful context of some consistency of having the `not` operator even for "simple" cases like (e is not null).
It's subtly different in that the != version will call an overloaded != operator if one exists and the "is not null" (or the semantically similar but less self-explanatory pre-9.0 "is object") won't.
Approaching natural language, in this case, gets things a bit more readable. I like it. Of course , for this example in particular , doing e?.(...) is better if the block of code is short;
Not sure pattern matching will age well. It seems to promote anti-OO design, may cause the switch statement to devolve into if/else, and creates another way to do the same thing.