All of the caveats basically boil down to "if you need to access the private backing field from anywhere other than the property getter/setter; then be aware it's going to have a funky non C# compliant field name".
In the EF Core and Automapper type of cases, I consider it an anti-pattern that something outside the class is taking a dependency on a private member of the class in the first place, so the compiler is really doing you a favor by hiding away the private backing field more obscurely.
> In the EF Core and Automapper type of cases, I consider it an anti-pattern that something outside the class is taking a dependency on a private member of the class in the first place, so the compiler is really doing you a favor by hiding away the private backing field more obscurely.
It's another variation of the "parse don't validate" dance. Just because you can do model validation in property setters doesn't always mean it is the best place to do model validation. If you are trying to bypass the setter in a DB Model, then you may have data in your database that doesn't validate, you just want to "parse" it and move on.
It is similar with auto-mapping scenarios, with the complication that automapping was originally meant to be the Validation step in some workflows and code architectures. I think that's personally why AutoMapper and other similar libraries have had a code smell to me as where those tools are often used are "parsing boundaries" more than they should be "validation boundaries" and the coupling between validation logic and AutoMapper logic to me starts to feel like a big ball of spaghetti to me versus a dedicated validation layer that is only concerned with validation not also doing a lot of heavy lifting in copying data around.
> be aware it's going to have a funky non C# compliant field name
That's longstanding behaviour. Ever since features such as anonymous types or lambdas arrived, they mean that classes and methods need to be generated from them. And of course these need names, assigned by the compiler. But these names are deliberately not allowed from the code. The compiler allows itself a wider set of names, including the "<>" chars.
I have heard them referred to as "unspeakable names" because it's not that they're unknown, you literally can't say them in the code.
> If you want to avoid this issue altogether, consider using a source generator library like Mapster. That way, mapping issues can be caught at build time rather than at runtime.
The only winning move is not to play. Mapping libraries, even with source generators, produce lots of bugs and surprising behavior. Just write mappers by hand.
I can appreciate the steady syntactic sugar that c# has been introducing these past years, they never feel like an abrupt departure from the consistency throughout. I often think that this is what java could have been if it hadn't been mangled by oracle's influence, unfortunately as much I like java it's pretty obvious that different parts have been designed by disjointed committee members focused on just one thing.
I feel like in a few more years and 2-3 major versions C# will have all the useful features of F#.
It will also keep being much more exciting because our benevolent corporate visionaries manage to add new gotchas with every major and some minor releases
I always shy away from syntax sugars. If I like a private field with setter and getter I write it into my code. The most of the code is written by autocomplete and if I do now like to se it I just fold it away. I have control over the naming and I can set breakpoints into the getter/setter to trap all those case where I somehow write rubbish. I also have the benefit of seeing the field in my debugger and can access them for hydration without the setter. I see no real use in such new keywords. Just my 2 cents
10 comments
[ 3.6 ms ] story [ 32.7 ms ] threadIn the EF Core and Automapper type of cases, I consider it an anti-pattern that something outside the class is taking a dependency on a private member of the class in the first place, so the compiler is really doing you a favor by hiding away the private backing field more obscurely.
It's another variation of the "parse don't validate" dance. Just because you can do model validation in property setters doesn't always mean it is the best place to do model validation. If you are trying to bypass the setter in a DB Model, then you may have data in your database that doesn't validate, you just want to "parse" it and move on.
It is similar with auto-mapping scenarios, with the complication that automapping was originally meant to be the Validation step in some workflows and code architectures. I think that's personally why AutoMapper and other similar libraries have had a code smell to me as where those tools are often used are "parsing boundaries" more than they should be "validation boundaries" and the coupling between validation logic and AutoMapper logic to me starts to feel like a big ball of spaghetti to me versus a dedicated validation layer that is only concerned with validation not also doing a lot of heavy lifting in copying data around.
That's longstanding behaviour. Ever since features such as anonymous types or lambdas arrived, they mean that classes and methods need to be generated from them. And of course these need names, assigned by the compiler. But these names are deliberately not allowed from the code. The compiler allows itself a wider set of names, including the "<>" chars.
I have heard them referred to as "unspeakable names" because it's not that they're unknown, you literally can't say them in the code.
e.g. by Jon Skeet, here https://codeblog.jonskeet.uk/category/async/ from 2013.
> they’re all "unspeakable" names including angle-brackets, just like all compiler-generated names.
The only winning move is not to play. Mapping libraries, even with source generators, produce lots of bugs and surprising behavior. Just write mappers by hand.