Microsoft startet mit den Previews zu .NET 11.0
Drei Monate nach dem Release von .NET 10.0 startet Microsoft den Preview-Reigen fĂĽr Version 11, vor allem mit Neuerungen beim Webfrontend-Framework Blazor.
(Bild: Pincasso/Shutterstock.com)
- Dr. Holger Schwichtenberg
.NET 11.0 steht ab sofort frisch zum Download bereit, wie ĂĽblich mit drei Runtime-Varianten und einem SDK, das sich nach der Installation mit Version 11.0.100-preview.1.26104.118 meldet.
Parallel sind auch Aktualisierungen von Visual Studio erschienen: Die Visual Studio 2022 hat Version 17.14.26 erreicht, Visual Studio 2026 kommt auf Version 18.3.0 und die Insiders-Version auf 11506.43.
Keine dieser Visual Studio-Versionen liefert .NET 11.0 mit, aber nach der getrennten Installation des .NET 11.0 SDKs steht in der Insider-Version .NET 11.0 zur Auswahl. Der Schnelltest ergab: In den anderen Visual-Studio-Versionen lassen sich .NET 11.0-Anwendungen nicht ĂĽbersetzen.
Neue Steuerelemente in Blazor
In Blazor hat Microsoft drei neue Komponenten eingebaut: Zum Ersten ermöglicht die Komponente <EnvironmentBoundary> HTML-Ausgaben abhängig von der Host-Umgebung (Development, Staging und Production). Über die Parameter Include und Exclude steuern Entwicklerinnen und Entwickler, in welchen Umgebungen eine Ausgabe stattfindet. In ASP.NET MVC und Razor Pages gab es dafür bisher schon einen Tag Helper. In Blazor musste man mit @if-Bedingungen arbeiten.
Folgender Code nutzt die neue Blazor-Komponente <EnvironmentBoundary>:
<EnvironmentBoundary Include="Development,Staging">
<div class="alert alert-warning">
<p>Debug oder Staging</p>
</div>
</EnvironmentBoundary>
<EnvironmentBoundary Exclude="Production">
<p>@DateTime.Now</p>
</EnvironmentBoundary>
Die beiden weiteren neuen Blazor-Komponenten heißen <Label> und <DisplayName>. Auch sie sind Pendants zu bestehenden Funktionen in den älteren Webframeworks. Bei beiden Komponenten geht es um die Beschriftung von Formularfeldern. In Blazor-Formularen mussten Entwicklerinnen und Entwickler bisher die Beschriftungen manuell per HTML-Tags erfassen:
<div>
<label for="companyName">Firma</label>
<InputText class="form-control" id="customerFullName" @bind-Value="company.CompanyName" />
<ValidationMessage For="@(() => company.CompanyName)" />
</div>
Auch wenn es Datenannotationen im Objektmodell gab wie:
<QuickGrid
OnRowClick="@HandleRowClick"
ItemsProvider="@itemsProvider"
TGridItem="BO.WWWings.Flight" …>
Nun kann sich Blazor mit <DisplayName> den passenden Anzeigenamen aus dem Objektmodell holen:
<label for="companyName"> <DisplayName For="() => company.CompanyName" /></label>
Die Komponente <Label> erlaubt eine weitere VerkĂĽrzung auf
<Label For="() => company.CompanyName" />
Auch ein Einbetten eines Eingabesteuerelements in <Label> ist möglich:
<Label For="() => company.CompanyName" >
<InputText class="form-control" id="customerFullName" @bind-Value="company.CompanyName" />
<ValidationMessage For="@(() => company.CompanyName)" />
</Label>
Zudem kann man mit Blazor nun auch die Mathematical Markup Language (MathML) zum Darstellen mathematischer Formeln im Browser interaktiv rendern. Zuvor konnte man mit Blazor nur HTML und SVG erzeugen.
Erweiterungen bestehender Funktionen in Blazor
Das bestehende Blazor-Steuerelement <QuickGrid> bekommt in .NET 11.0 Preview 1 das neue Ereignis OnRowClick():
<QuickGrid
OnRowClick="@HandleRowClick"
ItemsProvider="@itemsProvider"
TGridItem="BO.WWWings.Flight" …>
Dieses Ereignis kann man per synchroner oder asynchroner Methode behandeln:
void HandleRowClick(BO.WWWings.Flight f) { …. }
async Task HandleRowClick(BO.WWWings.Flight f) { …. }
OnRowClick() sorgt dafĂĽr, dass beim Ăśberfahren der Zeilen mit der Maus der Cursor Pointer (in der Regel eine Hand) angezeigt wird.
Die eingebaute Komponente <NavLink> und die Hilfsklasse NavigationManager bieten nun neben der absoluten auch eine relative Navigation vom aktuellen Standort aus an:
<NavLink href="ziel" RelativeToCurrentUri="true">
Zum Ziel
</NavLink>
und
void NavRelative()
{
// Navigate to a sibling page
NavigationManager.NavigateTo("ziel", new NavigationOptions
{
RelativeToCurrentUri = true
});
}
Die ebenfalls neue Methode GetUriWithHash() hängt einen Fragment-Bezeichner an die aktuelle URL an. NavigationManager.GetUriWithHash("Kapitel2") ergänzt beispielsweise #Kapitel2.
Vereinfachte Konfiguration in Blazor
Bei Blazor Server lassen sich die Eigenschaften der SignalR-Verbindung nun im Startcode Program.cs einfacher setzen als bisher:
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode(options =>
{
options.ConfigureConnection = dispatcherOptions =>
{
dispatcherOptions.CloseOnAuthenticationExpiration = true;
dispatcherOptions.AllowStatefulReconnects = true;
dispatcherOptions.ApplicationMaxBufferSize = 1024 * 1024;
};
});
Auch bei dem JavaScript-basierten Teil der Blazor-Konfiguration gibt es neue Verbesserungen für ältere Projekte, die noch blazor.server.js und blazor.webassembly.js als Clientbibliothek nutzen. Hier können Entwicklerinnen und Entwickler jetzt die gleiche Syntax wie bei der in .NET 8.0 eingeführten Clientbibliothek blazor.web.js verwenden, siehe den zugehörigen Abschnitt in den Release Notes.
Blazor WebAssembly unterstĂĽtzt jetzt auch die Schnittstelle IHostedService fĂĽr Hintergrunddienste im Webbrowser sowie die Schnittstelle IConfiguration zum Zugriff auf Umgebungsvariablen.
Neuerungen in der Basisklassenbibliothek
Auch in der Basisklassenbibliothek gibt es Neuerungen, von denen alle .NET-Anwendungsarten profitieren. Bereits seit .NET Core 3.0 gibt es die Klasse System.Text.Rune zur vereinfachten Handhabung von Unicode-Zeichen auĂźerhalb der Basic Multilingual Plane (BMP). Neu in .NET 11.0 ist, dass die Methoden der Klassen System.String und System.Text.StringBuilder sowie System.IO.TextWriter auch Instanzen der Klasse Rune als Parameter akzeptieren, beispielsweise bei IndexOf() und Replace():
string text = "▶ Urbi ⌂ et Orbi 🌍!";
Rune globe = new Rune(127757); // 🌍 127757
int index = text.IndexOf(globe); // 17
string replaced = text.Replace(globe, new Rune('↯')); // "▶ Urbi ⌂ et Orbi ↯!"
Mit der neuen Klasse RunePosition kann man die einzelnen Runen in einer Zeichenkette auflisten:
foreach (RunePosition pos in RunePosition.EnumerateUtf16(text))
{
Console.WriteLine($"Rune: {pos.Rune.Value}, Start: {pos.StartIndex}, Length: {pos.Length}");
}
Diese Zeilen liefern in Bezug auf „Hello 🌍 World“ folgende Ausgabe:
Rune: 9654, Start: 0, Length: 1
Rune: 32, Start: 1, Length: 1
Rune: 85, Start: 2, Length: 1
Rune: 114, Start: 3, Length: 1
Rune: 98, Start: 4, Length: 1
Rune: 105, Start: 5, Length: 1
Rune: 32, Start: 6, Length: 1
Rune: 8962, Start: 7, Length: 1
Rune: 32, Start: 8, Length: 1
Rune: 101, Start: 9, Length: 1
Rune: 116, Start: 10, Length: 1
Rune: 32, Start: 11, Length: 1
Rune: 79, Start: 12, Length: 1
Rune: 114, Start: 13, Length: 1
Rune: 98, Start: 14, Length: 1
Rune: 105, Start: 15, Length: 1
Rune: 32, Start: 16, Length: 1
Rune: 127757, Start: 17, Length: 2
Rune: 33, Start: 19, Length: 1
In der neuen Assembly System.IO.Compression.Zstandard.dll liefert Microsoft Klassen für die verlustfreie Komprimierung mit dem beim Facebook entwickelten Komprimierungsverfahren Zstandard (zstd). Zu den neuen Klassen gehören System.IO.Compression.ZstandardStream und System.IO.Compression.ZstandardEncoder sowie System.IO.Compression.ZstandardCompressionOptions. Laut Microsoft gilt: „Zstandard komprimiert auf der optionalen Stufe 2- bis 7-mal schneller als Brotli und Deflate und dekomprimiert auf der schnellsten Stufe 2- bis 14-mal schneller, wobei vergleichbare Kompressionsraten erzielt werden.“ Zstandard kann in .NET 11.0 auch bereits für die HTTP-Antwortkomprimierung zum Einsatz kommen.
Bei den Dateisystemklassen im Namensraum System.IO bietet die Klasse File nun die neuen Methoden File.CreateHardLink() und FileInfo.CreateAsHardLink() an, um Hard Links anzulegen. Zuvor konnten Entwicklerinnen und Entwickler seit .NET 6.0 nur symbolische Links mit File.CreateSymbolicLink() anlegen, was aber immer Administratorrechte erforderte.
Einige weitere neue Funktionen in der Basisklassenbibliothek beschreiben die Release Notes, darunter der neue FlieĂźkommatyp System.Numerics.BFloat16 und alternative Rundung bei Divisionen mit den Optionen Truncate, Floor, Ceiling, AwayFromZero und Euclidean sowie eine neue Methode Verify() bei einigen Klassen fĂĽr Hashverfahren.
Entity Framework Core unterstützt jetzt komplexe Typen einschließlich JSON-Mapping auch in Entitätsklassen, die Vererbung verwenden, wie in der Dokumentation zu EF Core 11.0 steht. Davon ausgenommen ist aber noch die Table-per-Hierarchy-Vererbung (TPH).
Parameter fĂĽr Collection Expressions in C# 15.0
Zu .NET 11.0 gehört wie üblich auch eine neue C#-Version, dieses Mal mit der Versionsnummer 15.0. In .NET 11.0 Preview 1 gibt es allerdings bisher nur ein neues Sprachfeature für C# 15.0: Collection Expression Arguments. Seit C# 12.0 gibt es in C# die Collection Expressions zur vereinfachten Initialisierung von Objektmengen, beispielsweise mit
List<int> magicNumbers1 = [6, 7, 42];
Diese Syntax mit den eckigen Klammern war aber nicht möglich, wenn man bei der Initialisierung der Menge Konstruktor-Parameter wie die Kapazität einer Objektmenge setzen wollte:
List<int> magicNumbers2 = new(100) { 6, 7, 42 };
oder sprechender
List<int> magicNumbers3 = new(capacity:100) { 6, 7, 42 };
Diesen Sonderfall kann man in C# 15.0 mit Collection Expression Arguments nun wie folgt ausdrĂĽcken, was die Syntax aber nicht wesentlich verkĂĽrzt:
List<int> magicNumbers3 = [with(capacity: 100), 6, 7, 42];
In Arbeit bei Microsoft fĂĽr C# 15.0 ist eine weitere Verbesserung der Collection Expressions: Diese sollen nun auch fĂĽr Dictionaries nutzbar sein, beispielsweise mit:
SortedDictionary<string, int> dic = ["six":6, "seven":7, "forty two":42];
Verbesserungen im .NET SDK
Wenn in einem Projekt mehrere Target-Frameworks angegeben sind wie in
<TargetFrameworks>net10.0-windows;net11.0-windows</TargetFrameworks>
fragt der .NET-Kommandozeilenbefehl dotnet run nun, welches Framework fĂĽr den Start verwendet werden soll;
Alternativ kann man das Framework wie bisher per Parameter angeben:
dotnet run --framework net11.0-windows
Für .NET MAUI gibt es für iOS und Android bei dotnet run zwei neue Parameter: --list-devices und --device. Mit dem ersten Parameter listet man alle Geräte auf, mit dem zweiten wählt man das Gerät beim Start. Auch hier fragt dotnet run nun interaktiv nach, falls es keine Angabe gibt.
Bei den Kommandozeilenbefehlen fĂĽr Entity Framework Core gibt es nun bei Update-Database beziehungsweise dotnet ef database update jeweils den neuen Flag-Parameter -add. Er sorgt dafĂĽr, dass ein Schemamigrationsschritt angelegt und sofort ausgefĂĽhrt wird. Zuvor musste man erst Add-Migration beziehungsweise dotnet ef migrations add aufrufen.
Das Hot Reloading mit dotnet watch hat Microsoft verbessert: Entwicklerinnen und Entwickler können nun ohne Neustart der Anwendung auch Projekt- und NuGet-Paketreferenzen ergänzen. Für die Aktualisierung von Browserfenstern beim Hot Reloading kann man nun den Port frei wählen via Umgebungsvariable DOTNET_WATCH_AUTO_RELOAD_WS_PORT.
In den Projekteinstellungen lässt sich jetzt mit <PublishReferenceSymbols>true|false</PublishReferenceSymbols> steuern, ob .pdb-Dateien erzeugt werden.
Weitere Neuerungen und Breaking Changes
Weitere Informationen zu .NET 11.0 Preview 1 finden sich in einem Blogeintrag von Microsoft. Dazu gehört, dass .NET-basierte WebAssembly-Anwendungen nun alternativ zur Mono Runtime auch die .NET Core Runtime verwenden können. Es heißt aber, dass diese Option erst in .NET 12.0 als stabil gelten wird.
Wie in jeder .NET-Version der letzten Jahre üblich, wird es auch in .NET 11.0 wieder Breaking Changes gegenüber der Vorgängerversion 10.0 geben. Einige wenige Breaking Changes sind bereits in Preview 1 enthalten.
Ausblick
.NET 11.0 soll im November 2026 erscheinen und einen Standard-Term-Support von zwei Jahren erhalten. Bis dahin ist mit insgesamt sechs weiteren Preview-Versionen von März bis August sowie jeweils einer Release-Candidate-Version im September und Oktober zu rechnen.
(rme)