C# (13)

Analysis against C# 13 (.NET 9). C# 12/13 add primary constructors, collection expressions, params collections, and lock type.

This assessment applies the coupling account — coupling as access to a shared resource, and the coupling floor [1], [2] — and the knowledge-embodiment theorem [3]; the language is assessed against its official reference [4].

1 Assessment

This page assesses C# in five parts: core coupling — what the language’s own constructs force; ecosystem coupling — what the surrounding platform, tooling, and community cost; engineering readiness — whether the artifact can be reproduced, verified, observed, worked in quickly, connected to other languages, and governed openly; the profile — the unscored facts a score cannot express; and the scoring detail — the mechanism marks and the arithmetic behind every score. A ✅ bullet marks a construct that helps. A ⚠️ or ❌ bullet marks a cost; the scoring model does not price every cost named here.

Core coupling 46/100 · Ecosystem coupling 60/100 · Engineering readiness 88/100

1.1 Core coupling

1.1.1 Type

  • ✅ Interfaces + extension methods: Can add behavior without coupling to classes
  • ✅ Generics with constraints: Better than Java (no erasure, value type generics)
  • ✅ LINQ separates iteration from logic: Query syntax decouples data operations
  • ⚠️ Inheritance still available: Can couple via class hierarchies
  • ✅ Nullable reference types (C# 8+): Separates nullable from non-nullable
  • ✅ File-scoped types (C# 11): file access modifier restricts visibility to a source file, tightening encapsulation
  • ❌ Null still exists alongside nullable types: Migration incomplete
  • ❌ Properties can have side effects: obj.Prop might do anything
  • ⚠️ .NET runtime allows reflection: Can break encapsulation

1.1.2 Construction

  • ✅ Object initializers decouple: new Person { Name = "Alice", Age = 30 }
  • ✅ Records (C# 9+) are immutable: Value semantics prevent coupling
  • ✅ Primary constructors (C# 12): Reduce construction boilerplate on class/struct
  • ✅ Collection expressions (C# 12): [1, 2, 3] unified syntax decouples creation from collection type
  • ⚠️ Constructors can have side effects: No enforcement of pure construction
  • ✅ DI built into ASP.NET Core: Framework-level construction decoupling
  • ❌ Static state couples: Singleton patterns common

1.1.3 Memory

  • ✅ .NET GC decouples memory: Generational GC (gen0, gen1, gen2, LOH)
  • ✅ No manual memory management for managed code: Safe by default
  • ⚠️ GC pauses affect latency: Server/workstation GC modes, background GC helps
  • ✅ IDisposable pattern for resources: Deterministic cleanup via using statement
  • ⚠️ Finalizers couple cleanup to GC: Non-deterministic timing
  • ⚠️ Stack-allocated structs: Value types avoid GC but couple to stack lifetime
  • ✅ Span reduces allocations: Stack-based memory without GC pressure

1.1.4 Error

  • ❌ Unchecked exceptions: No throws clause, errors hidden
  • ⚠️ Result types uncommon: Libraries exist (LanguageExt) but not idiomatic
  • ✅ Nullable pattern helps: ?. operator reduces null coupling

1.1.5 Concurrency

  • ✅ Async/await excellent: Best async syntax in mainstream languages
  • ✅ Task separates async: Clear distinction from sync code
  • ✅ Lock type (C# 13): Dedicated System.Threading.Lock with pattern-based using scoping — decouples synchronization from object casting
  • ❌ Can still use threads with shared state: Traditional coupling available
  • ✅ Immutable collections available: System.Collections.Immutable, FrozenSet/FrozenDictionary (C# 12+) prevent concurrent coupling with zero overhead

1.1.6 Platform

  • ✅ Open-source runtime and compiler: .NET is MIT licensed, and the Roslyn compiler is developed in the open
  • ✅ Cross-platform runtime: The same compiled library runs on Windows, Linux, macOS, Android, iOS, and WebAssembly (Blazor)
  • ✅ Multiple implementations: CoreCLR, Mono, and .NET Framework each run C# code, so the language is not bound to one runtime
  • ✅ No runtime version lock-in: Side-by-side runtime versions let an application pin its own .NET version

1.1.7 Trade-offs (not coupling)

  • async colours a method: The modifier changes what its callers must do, so synchronous and asynchronous code do not compose freely — a deliberate trade
  • Nullability checking is a project setting: <Nullable>enable</Nullable> turns the checks on per project, so adoption is incremental — a migration choice, not a forced dependency
  • Unsafe code stays in the language: Pointers, P/Invoke, and COM are available for what the managed runtime cannot serve, a deliberate escape hatch rather than a dependency
  • Two runtimes share the language: Code that must also run on .NET Framework limits itself to the common subset — a compatibility trade, not a coupling
  • Code generation is part of the build: Source generators and partial types let tooling contribute half of a class, which moves work into the compilation step

1.2 Ecosystem coupling

1.2.1 Performance

  • ✅ Excellent JIT optimization: CLR is highly optimized
  • ⚠️ GC pauses: Server and background modes bound the pause but do not remove it, and the collector decides when it runs (R2)
  • ✅ Tunable GC: Multiple GC modes for different scenarios
  • ✅ Span/Memory: Zero-copy optimizations decouple performance from allocations
  • ⚠️ Startup time: JIT warmup (mitigated by ReadyToRun)
  • ✅ Native AOT: Recent addition decouples from JIT

1.2.2 Ecosystem

  • ✅ Massive .NET ecosystem: NuGet has everything
  • ⚠️ Framework monoculture: ASP.NET Core and the Microsoft stack dominate, so the alternatives are not really alternatives (Ec6)
  • ✅ Excellent tooling: Visual Studio, Rider, VSCode
  • ✅ dotnet CLI: Standardized, consistent
  • ✅ Cross-platform: .NET runs everywhere
  • ✅ Great IDE support: IntelliSense, refactoring

1.2.3 Evolution

  • ✅ Excellent backward compatibility: Rarely breaks
  • ✅ Rapid innovation: New features every year
  • ✅ Nullable reference types: Opt-in migration
  • ✅ Modern features: Records, pattern matching, LINQ

1.2.4 Domain

  • ✅ Excellent for backend: ASP.NET industry standard
  • ✅ Great for desktop: WPF, WinForms, Avalonia
  • ✅ Strong for games: Unity uses C#
  • ✅ Good for mobile: Xamarin/MAUI
  • ⚠️ Web frontend: Blazor exists but less common

1.2.5 Learning

  • ✅ Gentle: Similar to Java, well-documented
  • ✅ Excellent docs: Microsoft docs are comprehensive
  • ⚠️ Many features: LINQ, async, delegates can overwhelm
  • ✅ Good tutorials: Lots of learning resources

1.2.6 Syntax

  • ✅ Less verbose than Java: Properties, expression bodies
  • ✅ LINQ syntax: Expressive, decouples queries
  • ⚠️ Type inference limited: Often need explicit types
  • ✅ Modern features: Pattern matching, records reduce boilerplate

1.2.7 Testing

  • ✅ xUnit, NUnit, MSTest: Mature frameworks
  • ✅ World-class debugger: Visual Studio debugger is best-in-class
  • ✅ Profiling tools: dotTrace, PerfView
  • ✅ Hot reload: Edit and continue

1.2.8 Security

  • ✅ Memory safe: GC prevents memory bugs
  • ✅ Type safe: Strong static typing
  • ✅ Nullable reference types: Eliminates many null bugs
  • ⚠️ Unsafe code: unsafe keyword bypasses safety
  • ⚠️ Serialization issues: JSON/XML vulnerabilities

1.3 Engineering readiness

1.3.1 Reproducibility

  • ❌ Dependencies resolve without a lock by default.

1.3.2 Supply chain

  • ⚠️ The package registry is a flat name space.

1.3.3 Observability

  • ✅ No charged mechanism in this dimension.

1.3.4 Feedback

  • ✅ No charged mechanism in this dimension.

1.3.5 Interop

  • ✅ No charged mechanism in this dimension.

1.3.6 Governance

  • ✅ No charged mechanism in this dimension.

1.4 Profile

Unscored, and kept separate from every score on purpose. The profile records what a mechanism price cannot express: what a running program costs, how well a coding model and an agent work in the language, and whether a safety-critical path exists.

1.4.1 Energy and cost

What this axis asks: what does a running program cost in energy and time?

  • ⚠️ Runs on a virtual machine, above native code in the energy and time benchmarks [5]; a causal re-analysis attributes most of the gap to execution time [6].

1.4.2 AI and agent readiness

What this axis asks: how well does a coding model and an agent work in this language?

  • ✅ A large training corpus and strong code-generation results: models write this language well [7], [8].

1.4.3 Safety certification

What this axis asks: is there a certified or standards-qualified path to a safety-critical system?

  • ⚠️ No certified or standards-qualified path for safety-critical systems.

1.5 Scoring detail

1.5.1 Core coupling Dimensions

Dimension Mechanism Description Present Cost
Type T1 dynamic no static check — 0
T2 weak static — 0
T3 dynamic/duck dispatch — 0
T4 no sum types ✅ −4
T5 no generics — 0
T6 no namespaces — 0
T7 type erasure/reflection ✅ −4
T8 operator overloading — 0
T9 inheritance required for polymorphism — 0
T10 no null-safety — 0
T11 no module boundary — 0
T12 no effect tracking ✅ −8
T13 async/sync colouring ✅ −8
T14 unchecked foreign boundary ✅ −4
Type subtotal −15 (−28)
Construction C1 global mutable state by default — 0
C2 no immutability by default ✅ −4
C3 constructors coupled to allocation — 0
C4 no constructor/validation — 0
Construction subtotal −4
Memory M1 manual deallocation — 0
M2 GC non-deterministic pauses ✅ −8
M3 no RAII ✅ −4
M4 no ownership model ✅ −8
Memory subtotal −15 (−20)
Error Er1 no structured path — 0
Er2 unchecked exceptions only ✅ −8
Er3 errors ignored/non-exhaustive — 0
Er4 no composable result type ✅ −4
Error subtotal −12
Concurrency K1 GIL/no parallel — 0
K2 shared mutable state default — 0
K3 manual sync no race detection ✅ −8
K4 no structured concurrency — 0
K5 no primitives — 0
Concurrency subtotal −8
Platform P1 cannot function outside one vendor/domain — 0
P2 single-vendor but other uses — 0
P3 legacy/discontinued platform — 0
Platform subtotal 0

Core Dimensions score: 46/100 — total cost = −54 (per-dimension subtotals are capped at −15; an uncapped cost is shown in parentheses where the cap bites).

1.5.2 Ecosystem coupling Dimensions

Dimension Mechanism Description Present Cost
Performance R1 interpreted no AOT/JIT — 0
R2 GC pauses ✅ −8
R3 JIT warmup ✅ −4
Performance subtotal −12
Ecosystem Ec1 no package manager — 0
Ec2 fragmented tooling — 0
Ec3 small/niche/discontinued — 0
Ec4 proprietary — 0
Ec5 platform-locked tooling — 0
Ec6 monoculture ✅ −8
Ec7 legacy burden — 0
Ecosystem subtotal −8
Evolution V1 breaking changes — 0
V2 frozen — 0
V3 discontinued — 0
V4 glacial standards — 0
Evolution subtotal 0
Domain D1 domain/vendor lock-in — 0
D2 poor domain fit — 0
D3 framework forces architecture ✅ −8
Domain subtotal −8
Learning L1 steep — 0
L2 large surface/multi-paradigm ✅ −4
L3 sparse docs — 0
Learning subtotal −4
Syntax S1 verbose — 0
S2 inconsistent — 0
S3 punctuation-heavy — 0
Syntax subtotal 0
Testing G1 weak tooling — 0
G2 poor debugging — 0
G3 runtime-only errors — 0
Testing subtotal 0
Security Q1 memory-unsafe — 0
Q2 dynamic/weak typing risk — 0
Q3 known vulnerability/injection ✅ −8
Security subtotal −8

Meta Dimensions score: 60/100 — total cost = −40 (per-dimension subtotals are capped at −15; an uncapped cost is shown in parentheses where the cap bites).

1.5.3 Engineering readiness Dimensions

Dimension Mechanism Description Present Cost
Reproducibility Y1 build not reproducible — 0
Y2 dependencies not pinned ✅ −8
Reproducibility subtotal −8
Supply chain Y3 no signed provenance — 0
Y4 registry without namespacing ✅ −4
Supply chain subtotal −4
Observability Y5 no stable tracing standard — 0
Y6 no structured logging — 0
Observability subtotal 0
Feedback Y7 slow build — 0
Y8 no fast in-editor analysis — 0
Feedback subtotal 0
Interop Y9 no foreign-function interface — 0
Y10 no portable target — 0
Interop subtotal 0
Governance Y11 single-vendor governance — 0
Y12 closed specification — 0
Governance subtotal 0

Readiness Dimensions score: 88/100 — total cost = −12 (per-dimension subtotals are capped at −15; an uncapped cost is shown in parentheses where the cap bites).

Verdict: C# has evolved strong coupling-reducing features (extension methods, LINQ, records, async/await, nullable types) while maintaining .NET compatibility. Better than Java for coupling reduction due to modern features. Main strength: async/await eliminates coupling in this dimension. Main weakness: unchecked exceptions hide failure coupling.


The formal development. The definitions, theorems, and proofs behind this page are published in:

All published papers

References

[1]
Y. Loth, “On the nature of coupling: All coupling as shared resource access.” Zenodo, Aug. 2026. doi: 10.5281/zenodo.21925122.
[2]
Y. Loth, “Coupling as a consequence of cohesion: Decomposition, the coupling floor, and domain-imposed coupling.” Zenodo, Aug. 2026. doi: 10.5281/zenodo.21925201.
[3]
Y. Loth, “On the nature of cohesion: Cohesion as correctness relative to a partitioning rule.” Zenodo, Jul. 2026. doi: 10.5281/zenodo.21703193.
[4]
Microsoft, “C# language specification.” Microsoft; ECMA-334 and ISO/IEC 23270, 2023. Available: https://learn.microsoft.com/en-us/dotnet/csharp/
[5]
R. Pereira et al., “Energy efficiency across programming languages: How do energy, time, and memory relate?” in Proceedings of the 10th ACM SIGPLAN international conference on software language engineering (SLE), 2017, pp. 256–267. doi: 10.1145/3136014.3136031.
[6]
N. van Kempen, H.-J. Kwon, D. T. Nguyen, and E. D. Berger, “It’s not easy being green: On the energy efficiency of programming languages,” in Proceedings of the 40th IEEE/ACM international conference on automated software engineering (ASE), 2025. doi: 10.1109/ASE63991.2025.00131.
[7]
S. Joel, J. J. Wu, and F. H. Fard, “A survey on LLM-based code generation for low-resource and domain-specific programming languages,” ACM Transactions on Software Engineering and Methodology, 2025, doi: 10.1145/3770084.
[8]
Y. Qing et al., “EffiBench-x: A multi-language benchmark for measuring efficiency of LLM-generated code,” in Advances in neural information processing systems 38 (NeurIPS), datasets and benchmarks track, 2025. doi: 10.48550/arXiv.2505.13004.