Thema: csharp
-
.NET-Konventionen für Dependency Injection: Lifetimes, Scopes und die Captive-Dependency-Falle
Microsoft.Extensions.DependencyInjection registriert Dienste an einer IServiceCollection mit den Lifetimes transient, scoped oder singleton und injiziert sie über öffentliche Konstruktoren; die dokumentierten Regeln lauten: nie einen scoped-Dienst in ein Singleton injizieren, den Container das entsorgen lassen, was er erzeugt hat, Service-Locator-Aufrufe vermeiden und Scopes validieren, damit Captive Dependencies bereits beim Start fehlschlagen, statt Zustand über Anfragen hinweg durchsickern zu lassen.
-
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#: ein Vertrag zur Kompilierzeit, keine Laufzeitprüfung
Mit <Nullable>enable</Nullable> behandelt der C#-Compiler string als nicht nullable und string? als nullable, verfolgt den Null-Zustand jedes Ausdrucks und warnt bei Widersprüchen; zur Laufzeit ändert sich nichts, string und string? sind derselbe Typ, und der Null-vergebende Operator ! sowie die Nullable-Analyse-Attribute ([NotNullWhen], [MemberNotNull]) sind die Mittel, um dem Compiler mitzuteilen, was er nicht ableiten kann.
Maschinenlesbar: JSON