Thema: dotnet
-
.NET-Konventionen für Dependency Injection: Lifetimes, Scopes und die Captive-Dependency-Falle
Microsoft.Extensions.DependencyInjection registriert Dienste auf einer IServiceCollection mit der Lifetime transient, scoped oder singleton und injiziert sie über öffentliche Konstruktoren; die dokumentierten Regeln lauten, nie einen scoped-Dienst in einen Singleton zu injizieren, den Container das entsorgen zu lassen, was er selbst erzeugt hat, Service-Locator-Aufrufe zu vermeiden und Scopes zu validieren, damit gefangene Abhängigkeiten (captive dependencies) schon beim Start scheitern, statt Zustand über Anfragen hinweg durchsickern zu lassen.
-
Welche Observability-Signale sollte ein JVM- oder .NET-Dienst standardmässig ausgeben, und mit welchem Overhead?
Offene Frage: Beide Laufzeitumgebungen bringen eingebaute Telemetrie mit (Flight Recorder und GC-Logging auf der JVM; EventPipe-Counter und dotnet-trace bei .NET), und beide bieten OpenTelemetry-Auto-Instrumentierung – doch es gibt kaum geteilte Belege dazu, welche davon in Produktion dauerhaft aktiv sein sollten, was sie kosten und welche tatsächlich Vorfälle verkürzt haben.
-
Einen Unit-Test in JUnit 5 und xUnit.net schreiben: Annotationen, Lifecycle und parametrisierte Fälle im Vergleich
JUnit Jupiter markiert Tests mit @Test, führt standardmässig @BeforeEach und @AfterEach um jeden Test auf einer frischen Instanz aus und steuert datengetriebene Fälle mit @ParameterizedTest plus einer Source-Annotation; xUnit.net verwendet [Fact], den Konstruktor und IDisposable für das Setup je Test auf einer frischen Instanz, [Theory] mit [InlineData] für Fälle sowie Fixtures für geteilten, teuren Kontext. Tests in beiden mit derselben Form zu schreiben, hält die Konventionen eines mehrsprachigen Teams im Gleichlauf.
-
C#-async/await-Stolpersteine: Sync-over-Async, async void und ConfigureAwait
Die klassischen Fehler in asynchronem C#-Code sind das Blockieren auf einem Task mit .Result, .Wait() oder GetAwaiter().GetResult() (Deadlocks unter einem Single-Thread-SynchronizationContext, Thread-Pool-Erschöpfung auf Servern), async-void-Methoden, deren Ausnahmen nicht abgefangen werden können, und ein falsch gesetztes ConfigureAwait(false), das in allgemeine Bibliotheken gehört und nicht in Anwendungscode.
-
NuGet-Abhängigkeiten pinnen: PackageReference, zentrale Paketverwaltung und packages.lock.json
NuGet löst beim Restore die niedrigste zutreffende Version jedes Pakets auf, sodass ein Restore driften kann, wenn neue Versionen oder gleitende Bereiche auftauchen; ein wiederholbarer Build deklariert Versionen einmalig in Directory.Packages.props, aktiviert RestorePackagesWithLockFile, damit packages.lock.json den vollständigen Abschluss festhält, committet die Lock-Datei für Anwendungen und restored in CI mit --locked-mode.
-
Nullable reference types in C#: a compile-time contract, not a runtime check
With <Nullable>enable</Nullable> the C# compiler treats string as non-nullable and string? as nullable, tracks the null-state of every expression and warns on mismatches; nothing changes at run time, string and string? are the same type, and the null-forgiving operator ! plus the nullable-analysis attributes ([NotNullWhen], [MemberNotNull]) are how you tell the compiler what it cannot infer.
Maschinenlesbar: JSON