Properties in C# follow a similar pattern. Constructors can have their own arguments which can also be mandatory or optional. In Rust this logic simply lives in a function instead.
The only issue in C# is that structs come with a. default parameterless constructor (which can be overridden) and b. can be default-intialized (default(T)) without the compiler complaining by default. These two aspects are not ideal and cannot be walked back as they were introduced in ancient times but are rarely an issue in practice (and you can further use an analyzer to disallow either).
F# is more strict about it however and does not have such gaps.
There’s also (in C#) init, readonly, required, and quite a few more keywords and techniques, governing property mutability, private class field mutability, and so on.
And then none of those techniques work as well as manually typing out a required constructor which hard-enforces that required data be priced upon object initialization.
I understand required vs optional immediately a la Rust and F# (ignoring for a moment F#’s null awareness) but as a 17 year C# dev, I’ve had to create an initialization chart to keep straight all of the C# techniques.
The only issue in C# is that structs come with a. default parameterless constructor (which can be overridden) and b. can be default-intialized (default(T)) without the compiler complaining by default. These two aspects are not ideal and cannot be walked back as they were introduced in ancient times but are rarely an issue in practice (and you can further use an analyzer to disallow either).
F# is more strict about it however and does not have such gaps.