4 ms·
The default C# style has always preferred a large dose of unnecessary runtime flexibility. Sometimes that comes in the form of lots of dynamic dispatch, sometim
by emn13 2y ago
The default C# style has always preferred a large dose of unnecessary runtime flexibility. Sometimes that comes in the form of lots of dynamic dispatch, sometimes it's DI, sometimes it's non-sealed overly large base-class types, and sometimes its some combination thereof - but the net effect is that it's not possible to reason about code by just reading it. Tooling becomes worse and/or less valuable because tooling too cannot reliably trace all possible code paths.
Additionally, Microsoft has an outsized influence on the C# ecosystem. As a result, they wrote quite a few architectural and style guidelines that, naturally, target themselves. It makes sense for a hyper-widely distributed library to consider things like binary compatibility as critical features, but the design rules that follow from that have zero utility for apps, and low utility for most libraries. The C# ecosystem also has an unhealthy veneration for MS provided code. While I'm sure most of the authors are quite competent, there's less experimentation and fewer hidden gems because the ecosystem is tilted towards being followers behind the framework providers path.
As a result, it's much harder to refactor code in that style than code in a less (runtime) flexible style, and it's worse when the libraries heavily used are frameworks that have so many extension points. There's a tradeoff between runtime flexibility and codebase flexibility, and the default .NET C# style heavily leans towards runtime flexibility, which isn't a good tradeoff for most software.