{"id":1020992,"date":"2026-05-15T13:10:15","date_gmt":"2026-05-15T13:10:15","guid":{"rendered":"https:\/\/www.europesays.com\/de\/1020992\/"},"modified":"2026-05-15T13:10:15","modified_gmt":"2026-05-15T13:10:15","slug":"net-11-0-preview-4-ein-bunter-strauss-von-api-erweiterungen","status":"publish","type":"post","link":"https:\/\/www.europesays.com\/de\/1020992\/","title":{"rendered":".NET 11.0 Preview 4: Ein bunter Strau\u00df von API-Erweiterungen"},"content":{"rendered":"<p>Die vierte Vorschauversion der kommenden .NET-Version 11.0 ist erschienen und <a href=\"https:\/\/dotnet.microsoft.com\/en-us\/download\/dotnet\/11.0\" rel=\"external noopener nofollow\" target=\"_blank\">steht zum Download bereit<\/a>. Parallel dazu hat Microsoft auch die Version 11811.120 von <a href=\"https:\/\/visualstudio.microsoft.com\/insiders\/\" rel=\"external noopener nofollow\" target=\"_blank\">Visual Studio 2026 Insiders<\/a> ver\u00f6ffentlicht, die zum Entwickeln von .NET-11.0-Anwendungen ben\u00f6tigt wird. Alternativ ist eine Arbeit mit Visual Studio Code und dem im SDK mitgelieferten Kommandozeilencompiler m\u00f6glich.<\/p>\n<p>        Weiterlesen nach der Anzeige<\/p>\n<p>    <img loading=\"lazy\" decoding=\"async\" alt=\"Dr. Holger Schwichtenberg\" height=\"293\" src=\"data:image\/svg+xml,%3Csvg xmlns='http:\/\/www.w3.org\/2000\/svg' width='696px' height='391px' viewBox='0 0 696 391'%3E%3Crect x='0' y='0' width='696' height='391' fill='%23f2f2f2'%3E%3C\/rect%3E%3C\/svg%3E\" style=\"aspect-ratio: 233 \/ 293; object-fit: cover;\" width=\"233\"\/><\/p>\n<p class=\"a-inline-textbox__synopsis\">\n          Dr. Holger Schwichtenberg hat Fachb\u00fccher zu .NET 10.0, C# 14.0, Blazor 10.0 und Entity Framework Core 10.0 ver\u00f6ffentlicht. Er arbeitet als Berater und Trainer bei www.IT-Visions.de. &#13;<\/p>\n<p>      <a href=\"https:\/\/www.heise.de\/imgs\/18\/5\/0\/8\/2\/7\/7\/2\/image1-2f754a675e7b3077.png\" rel=\"nofollow noopener\" target=\"_blank\"><\/p>\n<p>  <img loading=\"lazy\" decoding=\"async\" alt=\"Installation des .NET 11.0 SDK in der Version Preview 4\" height=\"737\" src=\"data:image\/svg+xml,%3Csvg xmlns='http:\/\/www.w3.org\/2000\/svg' width='696px' height='391px' viewBox='0 0 696 391'%3E%3Crect x='0' y='0' width='696' height='391' fill='%23f2f2f2'%3E%3C\/rect%3E%3C\/svg%3E\" style=\"aspect-ratio: 971 \/ 737; object-fit: cover;\" width=\"971\"\/><\/p>\n<p>      <\/a><\/p>\n<p>Installation des .NET 11.0 SDK in der Version Preview 4<\/p>\n<p>    <img loading=\"lazy\" decoding=\"async\" alt=\"betterCode() .NET 11.0\" height=\"1080\" src=\"data:image\/svg+xml,%3Csvg xmlns='http:\/\/www.w3.org\/2000\/svg' width='696px' height='391px' viewBox='0 0 696 391'%3E%3Crect x='0' y='0' width='696' height='391' fill='%23f2f2f2'%3E%3C\/rect%3E%3C\/svg%3E\" style=\"aspect-ratio: 1920 \/ 1080; object-fit: cover;\" width=\"1920\"\/><\/p>\n<p class=\"a-caption__source\">\n      (Bild:\u00a0King \/ stock.adobe.com)\n    <\/p>\n<p>Das ist neu in .NET 11.0: Dr. Holger Schwichtenberg und weitere Experten pr\u00e4sentieren am 17. November 2026 auf der Online-Konferenz <a href=\"https:\/\/net.bettercode.eu\/?wt_mc=intern.conf.dpunkt.konf_dpunkt_bcc_net.empfehlung-ho.link.link&amp;LPID=38418\" rel=\"external noopener nofollow\" target=\"_blank\">betterCode() .NET 11.0<\/a> die \u00c4nderungen f\u00fcr Entwicklerinnen und Entwickler in .NET SDK, C# 15.0 und mehr. Bis zur Ver\u00f6ffentlichung des Programms sind <a href=\"https:\/\/net.bettercode.eu\/tickets.php?wt_mc=intern.conf.dpunkt.konf_dpunkt_bcc_net.empfehlung-ho.link.link&amp;LPID=38418\" rel=\"external noopener nofollow\" target=\"_blank\">verg\u00fcnstigte Blind-Bird-Tickets<\/a> verf\u00fcgbar.<\/p>\n<p>Viel Neues f\u00fcr den Prozessstart<\/p>\n<p>Die Klasse System.Diagnostics.Process zur Verwaltung von Betriebssystemprozessen gibt es seit Version 1.0 des klassischen .NET Framework aus dem Jahr 2002. Prozesse startet man seitdem, indem man eine neue Instanz der Klasse erzeugt. Seit .NET Framework 2.0 (Jahr 2005) gibt es alternativ die statische Methode Process.Start(). 21 Jahre sp\u00e4ter erg\u00e4nzt Microsoft nun weitere alternative statische Methoden zum Prozessstart: Process.Run() und Process.RunAsync() sowie Process.RunAndCaptureText() und Process.RunAndCaptureTextAsync(). Das letztgenannte P\u00e4rchen liefert ein ProcessTextOutput-Objekt, mit dem man direkt auf Standardausgabe (ProcessTextOutput), Standardfehlerausgabe (StandardError) und R\u00fcckgabewert (ExitStatus.ExitCode) zugreifen kann, mit deutlich weniger Programmcode als dies bei der alten Start()-Methode notwendig ist, siehe Listing.<\/p>\n<p>Ein Abbruch des Kindprozesses ist \u00fcber ein Cancellation-Token m\u00f6glich. Anders als bei der Start()-Methode kehren alle neuen Methoden mit \u201eRun\u201c im Namen erst zum Aufrufer zur\u00fcck, wenn der Kindprozess beendet ist. Entwicklerinnen und Entwickler k\u00f6nnen dabei allerdings keine Ausgaben des Prozesses verarbeiten, w\u00e4hrend er l\u00e4uft.<\/p>\n<p>CancellationTokenSource cts = new CancellationTokenSource();<\/p>\n<p> ProcessTextOutput result = await Process.RunAndCaptureTextAsync(<br \/>\n     &#8222;robocopy.exe&#8220;, [@&#8220;t:\\Daten&#8220;, @&#8220;t:\\Daten_Backup&#8220;, &#8222;\/MIR&#8220;, &#8222;\/IS&#8220;], cts.Token);<\/p>\n<p> CUI.Print(&#8222;Neuer Prozess mit ID #&#8220; + result.ProcessId + &#8220; ist beendet!&#8220;);<\/p>\n<p> CUI.Line(&#8222;StandardOutput&#8220;);<br \/>\n CUI.Print(result.StandardOutput);<br \/>\n CUI.Line(&#8222;StandardError&#8220;);<br \/>\n CUI.PrintError(result.StandardError);<br \/>\n CUI.Line(&#8222;ExitStatus&#8220;);<br \/>\n CUI.Print(&#8222;Canceled? &#8220; + result.ExitStatus.Canceled);<br \/>\n if (result.ExitStatus.HasValue &amp;&amp; !result.ExitStatus.IsEmpty) PrintStatus(result.ExitStatus.ExitCode);<\/p>\n<p>Listing 1: Einsatz der neuen Methode Process.RunAndCaptureTextAsync()<\/p>\n<p>        Weiterlesen nach der Anzeige<\/p>\n<p>Eine weitere hinzugef\u00fcgte Methode zum Prozessstart ist Process.StartAndForget() zum Start eines Prozesses, ohne auf den erfolgreichen Start zu warten und ohne direkte Interaktionsm\u00f6glichkeiten mit dem neuen Prozess. Man kann lediglich \u00fcber die zur\u00fcckgelieferte Prozess-ID den neuen Prozess von au\u00dfen \u00fcberwachen, hat aber keinen Zugriff auf den R\u00fcckgabewert des Prozesses.<\/p>\n<p>int processId = Process.StartAndForget(<br \/>\n    &#8222;robocopy.exe&#8220;, [@&#8220;t:\\Daten&#8220;, @&#8220;t:\\Daten_Backup&#8220;, &#8222;\/MIR&#8220;, &#8222;\/IS&#8220;]);<\/p>\n<p>CUI.Print(&#8222;Neuer Prozess mit ID #&#8220; + processId + &#8220; ist gestartet!&#8220;);<\/p>\n<p>var p = Process.GetProcessById(processId);<br \/>\nwhile(!p.HasExited)<br \/>\n{<br \/>\n CUI.BusyIndicator();<br \/>\n Thread.Sleep(500);<br \/>\n}<\/p>\n<p>CUI.Line(&#8222;Neuer Prozess mit ID #&#8220; + processId + &#8220; ist beendet!&#8220;);<br \/>\n\/\/ PrintStatus(p.ExitCode); \/\/ System.InvalidOperationException: &#8218;Process was not started by this object, so requested information cannot be determined.&#8216;<\/p>\n<p>Listing 2: Einsatz der neuen Methode Process.StartAndForget()<\/p>\n<p>In der Klasse ProcessStartInfo, die bei Process.Start() verwendet wird, gibt es auch zwei neue Boolean-Optionen: Neu sind zum einen ProcessStartInfo.StartDetached zum Start eines unabh\u00e4ngigen Prozesses mit eigener Konsole, der weiterlebt, auch wenn der startende Prozess beendet wird. Mit ProcessStartInfo.KillOnParentExit erreicht man zum anderen, dass der Kindprozess endet, wenn der startende Prozess endet. Wenn man beide Optionen in Kombination einsetzt, erh\u00e4lt man eine separate Konsole, die aber endet, wenn der startende Prozess endet. W\u00e4hrend ProcessStartInfo.StartDetached auf allen Plattformen l\u00e4uft, meldet ProcessStartInfo.KillOnParentExit aktuell, dass es nur auf Windows funktioniert, denn im Quellcode bei Microsoft steht:<\/p>\n<p>[SupportedOSPlatform(&#8222;windows&#8220;)]<br \/>\npublic bool KillOnParentExit { get; set; }<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/process-api-improvements-in-dotnet-11\/#processstartinfo.killonparentexit\" rel=\"external noopener nofollow\" target=\"_blank\">In einem Blogeintrag<\/a> findet man schon den Hinweis darauf, dass Implementierungen f\u00fcr Android und Linux in Arbeit sind.<\/p>\n<p>F\u00fcr mit Process.Start() gestartete Prozesse gibt es auch die neuen Methoden ReadAllText() und ReadAllTextAsync(), mit denen man von einem beendeten Prozess gleichzeitig die Standardausgabe und die Fehlerausgabe erhalten kann:<\/p>\n<p>process.WaitForExit();<br \/>\n(string output, string error) = process.ReadAllText();<\/p>\n<p>Im Gegensatz zu dem bisherigen Ansatz<\/p>\n<p>string output = process.StandardOutput.ReadToEnd();<br \/>\nstring error = process.StandardError.ReadToEnd();<\/p>\n<p>besteht bei den neuen Methoden nicht die Gefahr eines Deadlocks.<\/p>\n<p>(De)-Komprimierung mit Span<\/p>\n<p><a href=\"https:\/\/www.heise.de\/news\/Microsoft-startet-mit-den-Previews-zu-NET-11-0-11173204.html\" rel=\"nofollow noopener\" target=\"_blank\">In .NET 11.0 Preview 1<\/a> hatte Microsoft die Zstandard-Komprimierung erg\u00e4nzt. Die Klassen ZstandardEncoder und ZstandardDecoder bieten dabei genauso wie die bereits in .NET Core 2.1 eingef\u00fchrten Klassen BrotliEncoder und BrotliDecoder die M\u00f6glichkeit, beim Komprimieren und Dekomprimieren mit den Typen Span und ReadOnlySpan zu arbeiten, ohne die aufwendige Speicherallokation bei Streams. Nun liefert Microsoft diese Option auch f\u00fcr die \u00e4lteren Klassen ZLibEncoder, DeflateEncoder und GZipEncoder sowie die zugeh\u00f6rigen Decoder, siehe Listing.<\/p>\n<p>CUI.H1($&#8220;Komprimiere Datei {BIGFILEPATH} via Span&#8220;);<\/p>\n<p>ReadOnlySpan sourceSpan = File.ReadAllBytes(BIGFILEPATH);<br \/>\nConsole.WriteLine(&#8222;L\u00e4nge=&#8220; + sourceSpan.Length);<br \/>\nlong maxCompressedLength = ZLibEncoder.GetMaxCompressedLength(sourceSpan.Length);<br \/>\nSpan compressedSpan = new byte[maxCompressedLength];<\/p>\n<p>\/\/ ZLibEncoder, DeflateEncoder, GZipEncoder, ZstandardEncoder oder BrotliEncoder<br \/>\nusing ZLibEncoder encoder = new();<br \/>\nOperationStatus status = encoder.Compress(<br \/>\n    sourceSpan, compressedSpan, out int bytesConsumed, out int bytesWritten,<br \/>\n    isFinalBlock: true);<\/p>\n<p>PrintStatus(compressedSpan, status);<\/p>\n<p>CUI.H1($&#8220;Dekomprimieren aus Span&#8220;);<\/p>\n<p>\/\/ ZLibDecoder, DeflateDecoder, GZipDecoder, ZstandardDecoder oder BrotliDecoder<br \/>\nusing ZLibDecoder decoder = new();<br \/>\nbyte[] decompressedSpan = new byte[sourceSpan.Length];<br \/>\nOperationStatus decompressStatus = decoder.Decompress(<br \/>\n  compressedSpan,<br \/>\n  decompressedSpan,<br \/>\n  out int compressedBytesConsumed,<br \/>\n  out int decompressedBytesWritten);<\/p>\n<p>PrintStatus(decompressedSpan, decompressStatus);<\/p>\n<p>Listing 3: Komprimierung und Dekomprimierung mit Span<\/p>\n<p>Parsen von Hex-Werten<\/p>\n<p>Die Flie\u00dfkommazahltypklassen Half, Single und Double k\u00f6nnen in den Methoden Parse() und TryParse() auch Zeichenketten mit Hexadezimalzahlen auswerten. Dazu m\u00fcssen Entwicklerinnen und Entwickler aber die Option NumberStyles.HexFloat angeben:<\/p>\n<p>static void TestDouble(double d, string doubleAsString )<br \/>\n{<br \/>\n string hex = d.ToString(&#8222;X&#8220;);<br \/>\n Console.WriteLine(hex);<br \/>\n double d1a = double.Parse(hex, NumberStyles.HexFloat);<br \/>\n Console.WriteLine(d1a);<br \/>\n CUI.Success(d1a == d); \/\/ True<br \/>\n double.TryParse(hex, NumberStyles.HexFloat, null, out double d1b);<br \/>\n Console.WriteLine(d1b);<br \/>\n CUI.Success(d1b == d); \/\/ True<br \/>\n}<\/p>\n<p>Pr\u00fcfung auf G\u00fcltigkeit bei UTF8 und UTF16<\/p>\n<p>Die Klassen System.Text.Unicode.Utf8 und System.Text.Unicode.Utf16 bieten nun zwei neue Methoden: IsValid() und IndexOfInvalidSubsequence(). Damit l\u00e4sst sich nun leichter die G\u00fcltigkeit einer Unicode-Zeichenkette pr\u00fcfen und zumindest die erste fehlerhafte Stelle ermitteln:<\/p>\n<p>ReadOnlySpan chars1 = &#8222;G\u00fcltiger Text: \\uD83D\\uDC4D&#8220;;<br \/>\nConsole.WriteLine(chars1);<br \/>\nbool check1 = Utf16.IsValid(chars1); \/\/ True<br \/>\nConsole.WriteLine(check1);<br \/>\nif (check1) CUI.Success(&#8222;OK&#8220;);<br \/>\nelse CUI.Warning(&#8222;Fehler bei Zeichen: &#8220; + Utf16.IndexOfInvalidSubsequence(chars1));<\/p>\n<p>ReadOnlySpan chars2 = &#8222;Ung\u00fcltiger Text: \\uD83D&#8220;;<br \/>\nConsole.WriteLine(chars2);<br \/>\nbool check2 = Utf16.IsValid(chars2); \/\/ False<br \/>\nif (check2) CUI.Success(&#8222;OK&#8220;);<br \/>\nelse CUI.Warning(&#8222;Fehler bei Zeichen: &#8220; + Utf16.IndexOfInvalidSubsequence(chars2));<\/p>\n<p>Utf8JsonWriter mit abweichenden Einstellungen wiederverwenden<\/p>\n<p>Bei dem im modernen .NET mitgelieferten JSON-Serialisierer, dem NuGet-Paket System.Text.Json, das auch im klassischen .NET Framework funktioniert, bietet die schon vorher bestehende Methode Reset() in der Klasse Utf8JsonWriter nun eine \u00dcberladung, in der man via JsonWriterOptions abweichende Einstellungen festlegen kann. Entwicklerinnen und Entwickler k\u00f6nnen damit Utf8JsonWriter-Instanzen mit abweichenden Einstellungen wiederverwenden:<\/p>\n<p>using var stream1 = new MemoryStream();<br \/>\nusing var writer = new Utf8JsonWriter(stream1, new JsonWriterOptions<br \/>\n  {<br \/>\n    Indented = true<br \/>\n  });<br \/>\n\u2026<br \/>\nusing var stream2 = new MemoryStream();<br \/>\nwriter.Reset(stream2, new JsonWriterOptions<br \/>\n   {<br \/>\n    Indented = false<br \/>\n   });<\/p>\n<p>Im Source Generator innerhalb von System.Text.Json <a href=\"https:\/\/github.com\/dotnet\/core\/blob\/main\/release-notes\/11.0\/preview\/preview4\/libraries.md#systemtextjson-improvements\" rel=\"external noopener nofollow\" target=\"_blank\">behebt Microsoft einige Schw\u00e4chen<\/a>.<\/p>\n<p>\n      Dieser Link ist leider nicht mehr g\u00fcltig.\n    <\/p>\n<p>Links zu verschenkten Artikeln werden ung\u00fcltig,<br \/>\n      wenn diese \u00e4lter als 7\u00a0Tage sind oder zu oft aufgerufen wurden.\n    <\/p>\n<p><strong>Sie ben\u00f6tigen ein heise+ Paket, um diesen Artikel zu lesen. Jetzt eine Woche unverbindlich testen \u2013 ohne Verpflichtung!<\/strong><\/p>\n","protected":false},"excerpt":{"rendered":"Die vierte Vorschauversion der kommenden .NET-Version 11.0 ist erschienen und steht zum Download bereit. Parallel dazu hat Microsoft&hellip;\n","protected":false},"author":2,"featured_media":1020993,"comment_status":"","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[135],"tags":[14235,219482,43023,29,219483,30,196,199,190,189,194,191,193,192],"class_list":{"0":"post-1020992","1":"post","2":"type-post","3":"status-publish","4":"format-standard","5":"has-post-thumbnail","7":"category-wissenschaft-technik","8":"tag-net","9":"tag-net-11-0","10":"tag-blazor","11":"tag-deutschland","12":"tag-entity-framework-core","13":"tag-germany","14":"tag-it","15":"tag-microsoft","16":"tag-science","17":"tag-science-technology","18":"tag-technik","19":"tag-technology","20":"tag-wissenschaft","21":"tag-wissenschaft-technik"},"share_on_mastodon":{"url":"","error":""},"_links":{"self":[{"href":"https:\/\/www.europesays.com\/de\/wp-json\/wp\/v2\/posts\/1020992","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.europesays.com\/de\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.europesays.com\/de\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.europesays.com\/de\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.europesays.com\/de\/wp-json\/wp\/v2\/comments?post=1020992"}],"version-history":[{"count":0,"href":"https:\/\/www.europesays.com\/de\/wp-json\/wp\/v2\/posts\/1020992\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.europesays.com\/de\/wp-json\/wp\/v2\/media\/1020993"}],"wp:attachment":[{"href":"https:\/\/www.europesays.com\/de\/wp-json\/wp\/v2\/media?parent=1020992"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.europesays.com\/de\/wp-json\/wp\/v2\/categories?post=1020992"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.europesays.com\/de\/wp-json\/wp\/v2\/tags?post=1020992"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}