.NET
.NET ecosystem rejection due to accumulated pain
9Experienced .NET developers are actively avoiding new .NET projects and migrating to Go, Python, Node.js, and PostgreSQL on AWS due to years of breaking changes, deprecated technologies, and migration pain. C# is perceived as dying for backend/web development.
Cross-platform certificate store abstraction broken on Linux
8The certificate store implementation is based on 2002-era Windows APIs that don't translate to Linux. Attempting to run .NET applications on Kubernetes with Linux requires workarounds like Hashicorp Vault, causing multi-month project delays.
Outdated .NET versions lacking modern features
7Developers maintaining codebases on unsupported or feature-limited .NET versions (Framework 4.8, Core 3.1, .NET 5-6) struggle to adopt modern C# features and syntax improvements. The path to upgrading to LTS versions is unclear and refactoring requires careful planning.
Enterprise .NET environments stifle innovation and skill growth
7Large enterprise .NET deployments enforce rigid processes, pre-approved design patterns, locked-down machines, and strict governance. Developers have no agency to fix broken systems or optimize workflows, leading to skill atrophy and mediocrity as the goal.
Thread-Safe Dictionary Implementation Complexity
6Manual implementation of thread-safe dictionaries using locks is error-prone and inefficient in multi-threaded scenarios, causing developers to either reinvent the wheel or face concurrency bugs.
Performance optimization complexity and poor benchmarks
6Identifying and fixing performance bottlenecks in C# is difficult, requiring deep understanding of memory management and resource allocation. C# ranks 22nd in TechEmpower performance benchmarks, necessitating use of profiling tools like dotTrace.
Limited Cross-Platform Support
6Although .NET Core improved cross-platform capabilities, C# was originally Windows-centric, and achieving true cross-platform compatibility (macOS, Linux) without code rewrites remains a significant challenge.
Ecosystem Centralization Around Microsoft
5While .NET is open source, the ecosystem is heavily driven by Microsoft's strategic goals, making it difficult to integrate with non-.NET tools and reducing appeal for developers working outside the Microsoft stack.
Legacy Codebase Verbosity and Boilerplate
5Many existing C# projects contain excessive boilerplate and outdated patterns, requiring developers entering the ecosystem to navigate legacy code that doesn't reflect the language's modern capabilities.
Limited library ecosystem and missing essential tools
5C# developers often face a lack of access to certain libraries or tools essential for their projects. When specific functionality is unavailable in the .NET framework, developers must search for alternative solutions, delaying development.
AutoMapper overuse despite poor fit
5AutoMapper has become the de facto mapping library in .NET despite its own creator recommending against use cases where >80% of fields are manually mapped. Developers adopt it even when inappropriate, leading to unmapped field issues and invalid mapping flags.
Limited Presence in Startup and Open-Source Communities
4C# has less visibility in startup environments and open-source communities compared to JavaScript, Python, or Go, limiting exposure to cutting-edge tools and reducing collaboration opportunities outside enterprise settings.
Dictionary Resizing and Rehashing Performance Impact
4Failing to preset Dictionary capacity causes expensive Resizing and Rehashing operations when capacity is exceeded, significantly increasing memory allocation overhead if data volume is known.
Confusing .NET and C# naming conventions
4Microsoft's rebranding of .NET Core to .NET and frequent changes to target framework monikers (e.g., .netcoreapp3.X to .net5+) creates confusion. The naming strategy makes it harder for developers to understand version compatibility, especially when .NET Framework 4.0 still exists alongside .NET 5+.
Imperative Code Patterns Reduce Maintainability
4Developers frequently write manual collection iterations and imperative statements for simple operations instead of using declarative alternatives, resulting in less maintainable and unnecessarily verbose code.
Empty Collection Allocation Overhead
4Habitually allocating new empty collections (arrays, lists) instead of using cached singletons causes unnecessary memory pressure and increases Garbage Collection overhead, especially in high-frequency loops.
Reinventing collections instead of using .NET libraries
4Developers unnecessarily create custom collection objects when comprehensive built-in options exist in .NET, including specialized collections like persistent tree data structures and priority queues. This wastes time and introduces maintenance burden.