Also, basic object initialization in C# has turned into a nightmare with recent versions. You need a flowchart to select among the 18 syntax options which suite your current needs.
With F# (and other newer languages), record fields are either `T` or `T option`. No need to worry about whether the value needs to be computed in a constructor and then remain immutable, whether it needs to be initialized by an object initializer and/or a constructor or not, whether it needs to remain interior-ly mutable throughout the life of the record, and so on. (Although as I recall you do still need to consider null values assigned to non-nullable references in your F# code that consumes C#.)
IMO its generally more readable as well to non-dev than C# and to dev's outside the Java/C# ecosystem (e.g. Node, Go, etc). I've shown F# code back in the day to non-tech stakeholders and they typically understand it (e.g. data modelling).
It's not always about the features such as keywords, built-in functionality and types. It's also how language features work together.
C# is more fit for an imperative or OOP style when F# is more fit for a functional style.
Trying to use a functional pipeline instead of DI.
And while I agree that I don't love some of the object initialization patterns C# allows--I respect that other people might have different style than me and don't mind ignoring that those styles exist when writing my own stuff :)
My general rule goes something like:
1. Use record types for any simple data structure
2. Avoid using primary constructors (even on record types).
3. Use { get; init; } properties for everything unless there's a good reason not to.
4. For things that need to carry internal state, have different methods for mutations, emit events, etc., use a class with regular old constructors and either { get; } (for immutable) or { get; private set; } (mutable) properties as needed.