.NET 8.0 und C# 12.0 erscheinen heute: Viel Neues für Blazor und C#-Compiler

Im Rahmen der .NET Conf 2023 wird Microsoft heute die endgültigen Versionen von .NET 8.0 und C# 12.0 freigeben. Während der Support des im November 2022 erschienenen Vorgängers .NET 7.0 schon im Mai 2024 endet, erhält .NET 8.0 einen Long-Term Support (LTS) von drei Jahren, also bis November 2027. Das vorherige LTS-Release .NET 6.0 unterstützt Microsoft noch bis zum November 2025.

Anzeige

.NET 8.0 wird auf der Downloadseite zur Verfügung gestellt. In den letzten Jahren war dies immer schon einige Stunden vor der offiziellen Verkündung der Fall.

Für .NET 8.0 benötigen Entwickler die Entwicklungsumgebungen Visual Studio 2022 in Version 17.8, die ebenfalls heute Abend als stabile Version erscheinen wird. Auch das kostenfreie Visual Studio Code ist mit aktuellem C#-Add-on möglich.

Entwickelt wurde .NET 8.0 in den letzten 12 Monaten. Seitdem hat Microsoft sieben Preview-Versionen und zwei Release-Candidates veröffentlicht, über die heise Developer jeweils berichtete.

Umsteiger von .NET 6.0 oder .NET 7.0 auf .NET 8.0 müssen nicht nur das Target Framework in der Projektdatei beziehungsweise zentralen Build-Konfigurationsdatei Directory.Build.props auf <TargetFramework>net8.0</TargetFramework> ändern, sondern auch die zahlreichen Breaking Changes berücksichtigen. Diese dokumentiert Microsoft in Listen:

Dabei hat Microsoft das Darstellungsformat geändert. In der Liste zu .NET 7.0 wurden nur noch in zwei Spalten “Binary compatible” und “Source compatible” unterschieden. In .NET 8.0 gibt es nun drei Kategorien “Binary incompatible”, “Binary incompatible” und “Behavioral change”. .NET 8.0 hat ähnlich viele Breaking Changes wie die Vorgängerversion.

Das Webframework Blazor gibt es seit Version 3.1 des modernen .NET, das damals noch .NET Core hieß. Bisher hatten Entwicklerinnen und Entwickler für Single-Page-Webanwendungen die Qual der Wahl zwischen Blazor Server und Blazor WebAssembly, die sich aufgrund der Vor- und Nachteile beider Architekturen in einigen Praxisfällen wie die Wahl zwischen Pest und Cholera anfühlte. Behelfen konnte man sich, in dem man eine Webanwendung für verschiedene Nutzergruppen oder Standorte in beiden Architekturen anbot.




Heise Developer und die .NET-Experten von www.IT-Visions.de werden dem deutschsprachigen Publikum den fertigen Stand von .NET 8.0 21. November 2023 im Rahmen der Online-Konferenz Better Code .NET 8.0 präsentieren. Bekannte .NET-Experten stellen alle wesentlichen Funktionen anhand von Praxisbeispielen vorstellen:

  • Die Neuerungen von .NET 8.0: SDK, Runtime und Basisklassen
  • Einfacher lesbarer, stabilerer Code mit C# 12.0
  • Alle Neuerungen von ASP.NET Core 8.0 und Blazor 8.0
  • Neues beim OR-Mapping mit Entity Framework Core 8.0
  • Das hat sich mit Windows Forms 8.0, WPF 8.0 und WinUI 3 verändert
  • Cross-Plattform-Entwicklung mit .NET MAUI 8.0
  • Ausblick auf .NET 9.0

.NET 8.0 erlaubt nun, beide Architekturen in einer einzigen Webanwendung zu vereinen. Der neue Rendering-Modus “Auto” rendert eine Webanwendung zunächst per Blazor Server mit Interaktivität per Websocket-Verbindung (siehe .NET 8.0 Preview 7 bringt Auto-Modus für Blazor). Nachdem im Hintergrund die umfangreichen Dateien für Blazor WebAssembly nachgeladen wurden, kann die Webanwendung zum rein lokalen Rendering im Browser übergehen, und die Websocket-Verbindung wird wieder beendet. Der Autor hat dazu die Beispielanwendung MiracleList erstellt, für deren Zugang eine kostenlose Registrierung erforderlich ist.

Außerdem ermöglicht Blazor 8.0 jetzt erstmals ein reines serverseitiges Rendern einer Multi-Page-Webanwendung. Microsoft nannte dieses Architekturmodell in der Preview-Phase (siehe Vorschau auf .NET 8.0: SPA-Inseln beim Server-side Rendering) noch “Blazor Server-Side-Rendering (SSR)”, hat sich aber in der endgültigen Version entschlossen, SSR für “Static-Server-Rendering” stehen zu lassen – mit dem Ziel, eine klarere Abgrenzung zu Blazor Server zu schaffen. Aber auch die neue Wortwahl kann zu Verwirrungen führen, weil einige Webframeworks unter dem Begriff “Static-Side-Generation” ein Rendering zur Entwicklungszeit anbieten. Blazor SSR rendert aber nicht zur Entwicklungszeit, sondern zur Laufzeit.

Die Architektur von Blazor SSR entspricht grundsätzlich dem, was in .NET bisher mit ASP.NET Core Model-View-Controller (MVC) und ASP.NET Core Razor Pages angeboten wurde. Allerdings kann Blazor SSR mit zusätzlichen Features punkten:

  • Blazor SSR bietet im Gegensatz zu MVC/Razor Pages ein echtes Komponentenmodell, bei dem sich Komponenten leicht ineinander einbetten lassen.
  • Die Razor-Template-Syntax in Blazor SSR bietet mehr Funktionen als die Razor Views und Razor Pages.
  • Asynchron gerenderte Inhalte lassen sich in der HTTP-Antwort nachsenden (Streaming).
  • Seitenteile können einzeln gesendet werden (Enhanced Navigation).
  • In einer statisch gerenderten Site können Entwicklerinnen und Entwickler SPA-Inseln (einzelne Seiten oder auch Seitenteile) einbetten, die mit Blazor Server, Blazor WebAssembly oder im Auto-Modus laufen.

Während Blazor SSR im Kern ohne JavaScript läuft, erfordern die letzten drei Punkte die Einbindung der von Microsoft in .NET mitgelieferten JavaScript-Datei blazor.web.js.

Man kann sicherlich sagen: Das Grab für MVC und Razor Pages ist durch die Einführung von Blazor SSR schon ausgehoben, auch wenn Microsoft die Beerdigung der beiden älteren Modelle bisher nicht verkündet hat.

Ein Praxisfall für Blazor SSR mit SPA-Inseln ist eine öffentliche Firmenwebsite, die in Hinblick auf Search Engine Optimization (SEO) nicht als SPA realisiert ist. Einzelne Teile der Website implementiert man dann aber als SPA-Inseln, beispielsweise das Kontaktformular, die Standortsuche und den Produktkonfigurator, um Benutzerinnen und Benutzern in Formularen eine bessere User Experience (UX) zu geben.



ASP.NET Core MVC und ASP.NET Core Razor Pages im Vergleich zu den Blazor-Architekturen in .NET 8.0 (Abb. 1)

(Bild: Holger Schwichtenberg)

Abbildung 1 zeigt die Architekturen ASP.NET Core MVC, ASP.NET Core Razor Pages, Blazor SSR ohne Streaming und Blazor SSR mit Streaming sowie Blazor Server und Blazor WebAssembly im Vergleich. Von dem bei der Erstankündigung am 24. Januar 2023 auf YouTube verkündeten Oberbegriff “Blazor United” für die neuen Funktionen ist Microsoft wieder abgekommen.

Zudem hat Microsoft die Projektvorlagen für Blazor aufgeräumt (siehe Abbildung 2 und .NET 8.0: Zweite Preview beschleunigt WebAssembly-Anwendungen): Fast alle Möglichkeiten von Blazor SSR, Blazor WebAssembly und Blazor Server findet man in der Vorlage “Blazor Web App”. Lediglich für Blazor-WebAssembly-Anwendungen, die unabhängig von einem ASP.NET Core-basierten Webserver laufen, gibt es die getrennte Vorlage “Blazor WebAssembly Standalone App” sowie eine Vorlage für hybride Blazor-Anwendungen auf Basis von .NET MAUI.



Abbildung 2: Blazor-Arten vor und nach .NET 8.0

(Bild: Holger Schwichtenberg)

In der RTM-Version von Blazor 8.0 wird Microsoft noch einige Änderungen vornehmen und Schwächen beheben. Dazu gehört, dass in der Projektvorlage die neue Direktive @rendermode zum Einsatz kommt. Zum Beispiel findet sich statt

@attribute [RenderModeInteractiveServer]

dort nun

@rendermode InteractiveServer

Das in Release Candidate 2 für einige Fehlerkorrekturen erforderliche NuGet-Paket Microsoft.Net.Compilers.Razor.Toolset kann in Projekten auf Basis der RTM-Version entfallen.

In C# 12.0 gibt es nur ungefähr halb so viele Syntax-Neuerungen wie im Vorgänger C# 11.0. Die drei bedeutenden Neuerungen sind:

  • Vereinfachte Initialisierung und Zuweisung für Mengen,
  • Primärkonstruktoren und
  • optionale Lambda-Parameter.

In C# 12.0 können Entwicklerinnen und Entwickler Mengen nun in der gleichen Syntax mit eckigen Klammern wie in JavaScript/TypeScript zuweisen, beispielsweise

List<int> d = [1,2,3];

Span<int> b = [1,2,3];

string[] sites1, sites2, sites3 = ["www.dotnetframework.de", "www.dotnet8.de"];
sites1 = ["www.dotnet-doktor.de", "dotnet-lexikon.de"];
sites2 = [];

Der Spread-Operator erzeugt ein Array aus den Elementen anderer Arrays:

string[] allSitesAsArray = 
  [.. sites1, .. sites2, "www.IT-Visions.de", .. sites3];

Primärkonstruktoren für Klassen gab es schon in C# 6.0 als Prototyp, sie kamen im Jahr 2015 allerdings nicht in das fertige Produkt. Nur Record-Typen, die es seit C# 9.0 gibt, haben bisher Primärkonstruktoren. In C# 12.0 ist die Syntax mit Parametern hinter dem Klassennamen auch für Klassen erlaubt. Anders als bei Record-Typen erzeugen Primärkonstruktoren bei Klassen jedoch keine öffentlichen Properties. Um öffentlich auf die im Primärkonstruktor übergebenen Daten zugreifen zu können, muss man die Konstruktorparameter für Zuweisungen verwenden:

/// <summary>
/// Klasse mit Primärkonstruktor 
/// </summary>
public class Person(Guid personGuid, string name)

 public Guid PersonGuid  get; set;  = personGuid;
 public string Name  get; set;  = name;
 
 public Person() : this(Guid.Empty, "")
 
 
 
 public override string ToString()
 
  return $"Person personGuid: Name";
 

Lambdas haben in den letzten Jahren an immer mehr Stellen in der .NET-Programmierung Methoden ersetzt. Allerdings erlaubten Lambdas bisher keine optionalen Parameter. Das hat sich in C# 12.0 geändert. Anstelle folgender Funktion mit optionalem Parameter z

public decimal Calc(decimal x, decimal y, decimal z = 1)

 return (x + y) * z;

ist in C# 12.0 nun folgender Lambda-Ausdruck erlaubt:

var calc = (decimal x, decimal y, decimal z = 1) => (x + y) * z;

Der letztes Jahr in .NET 7.0 eingeführte, aber dort noch auf Konsolenanwendungen beschränkte Ahead-of-Timer-Compiler “Native AOT” kann in .NET 8.0 nun auch Worker Services, gRPC-Dienste und ASP.NET Core WebAPIs (aber nur, wenn diese als Minimal-APIs angelegt sind) übersetzen. Datenbankzugriffe sind nur per ADO.NET möglich; Entity Framework Core funktioniert nicht mit dem AOT-Compiler.

Wie in jeder der letzten .NET-Versionen hat Microsoft auch diesmal die Basisklassenbibliothek erweitert. Dazu gehören:

  • Neue Validierungsannotationen im Namensraum System.ComponentModel.DataAnnotations, darunter [AllowedValues], [DeniedValues] und [Base64String] sowie Erweiterungen bei [Range] und [Length].
  • Eingefrorene Objektmengen: FrozenSet<T> und FrozenDictionary<T, T> im neuen Namensraum System.Collections.Frozen.
  • Neue Zufallsfunktionen in der Klasse System.Random: Zufallsreihenfolge mit Random.Shared.Shuffle() und Zufallauswahl via Random.Shared.GetItems().
  • Neue Methoden zum Auslösen von Fehlern in Methodenparametern wie ArgumentOutOfRangeException.ThrowIfZero(), ArgumentOutOfRangeException.ThrowIfNegative(), ArgumentOutOfRangeException.ThrowIfNegativeOrZero() und ArgumentOutOfRangeException.ThrowIfGreaterThan().
  • Privilegien-Abfrage mit System.Environment.IsPrivilegedProcess.
  • Dependency Injection mit Schlüsseln: services.AddKeyedSingleton<T1, T2>("Name") und serviceProvider.GetKeyedService<T1>("Name").
  • Zeitabstraktion mit der neuen Klasse System.TimeProvider.
  • Parse() und TryParse() in der Klasse System.Net.IPNetwork.
  • Razor-Template-Rendering außerhalb von Blazor in beliebigen .NET-Anwendungen mit der Klasse Microsoft.AspNetCore.Components.Web.HtmlRenderer im NuGet-Paket Microsoft.AspNetCore.Components.Web.
  • Source-Generator für das Component Object Model (COM): [GeneratedComInterface] und [GeneratedComClass] im Namensraum System.Runtime.InteropServices.Marshalling.
  • Einige neue Code-Analyzer, die Verbesserungen vorschlagen, beispielsweise hinsichtlich des Einsatzes von Equals() statt Case-Insensitive-Vergleichen mit ToLower()/ToUpper(), StartsWith() statt IndexOf() == 0 und Length/Count statt Any().

Ein kostenfreies Cheat Sheet mit den wichtigsten Neuerungen in C# 12.0 und der .NET-Basisklassenbibliothek findet sich auf der Website des Autors.

Zudem gibt es umfangreiche Verbesserungen beim Objekt-Relationalen Mapper Entity Framework Core in Version 8.0. Dazu gehören:

  • Mapping für die in .NET 6.0 eingeführten System.DateOnly und System.TimeOnly auch im Microsoft SQL Server,
  • Datentypen long und ulong für Timestamp-Spalten als Alternative zu Byte-Arrays,
  • Mapping von Arrays und Listen elementarer Typen auf JSON-Zeichenketten,
  • JSON-Mapping von Klassen mit ToJson() auch für SQLite-Datenbanken,
  • Table Splitting mit Complex Types als Alternative zu den bisher verfügbaren Owned Types via Annotation [ComplexType] oder Fluent-API per Methodenaufruf ComplexProperty(),
  • hierarchische Daten im SQL Server mit dem SQL Server-Spaltentyp “hierarchyid” im NuGet-Paket Microsoft.EntityFrameworkCore.SqlServer.HierarchyId,
  • Mapping von SQL-Abfragen auf beliebige, nicht in der Kontextklasse registrierte Typen mit ctx.Database.SqlQuery() und ctx.Database.SqlQueryRaw(),
  • Das Lazy Loading funktioniert auch bei No-Tracking-Abfragen.
  • Abschalten des Lazy Loading für einzelne Beziehungen mit EnableLazyLoading(false),
  • Asynchrones explizites Nachladen mit LoadAsync(),
  • Automatisch begrenzte Länge der Diskriminatorspalten bei Table-per-Hierarchy-Mapping,
  • Bessere SQL-Übersetzung des LINQ-Operators Contains(),
  • Übersichtlichere SQL-Generierung aus LINQ-Abfragen ohne überflüssige Klammern.
  • Abfrage der Objekte im lokalen Zwischenspeicher mit Local.FindEntry() und Local.GetEntries().
  • Statusabfrage, ob es Änderungen im Objektmodell gibt, für die es noch keine Datenbankschema-Migration gibt: via Kommandozeile dotnet ef migrations has-pending-model-changes.
  • Festlegen des von Entity Framework Core intern verwendeten Wächterwerts, um festzustellen, dass ein Wert nicht der im Datenbankmanagementsystem hinterlegte Standardwert ist: HasSentinel().
  • Die in Entity Framework Core 7.0 eingeführten Methoden ExecuteUpdate() und ExecuteDelete() funktionieren in Version 8.0 auch in Fällen, bei denen mehrere Entitätsklassen auf eine einzige Tabelle (z.B. bei der TPH-Vererbung) abgebildet sind.

Entity Framework Core 8.0 läuft nur auf .NET 8.0; bis Preview 6 waren auch .NET 6.0 und 7.0 als Basis möglich.

Weitere Neuerungen findet man in ASP.NET Core innerhalb und außerhalb von Blazor, im JSON-Serializer sowie auch in den Desktop-UI-Frameworks Windows Forms und WPF.


(rme)

Zur Startseite

source site