{"id":32255,"date":"2021-03-11T11:48:12","date_gmt":"2021-03-11T18:48:12","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=32255"},"modified":"2021-03-16T11:17:38","modified_gmt":"2021-03-16T18:17:38","slug":"announcing-net-6-preview-2","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-net-6-preview-2\/","title":{"rendered":"Announcing .NET 6 Preview 2"},"content":{"rendered":"<p>Today, we are glad to release .NET 6 Preview 2. It includes new APIs, runtime performance improvements, and early builds of .NET MAUI. It also includes builds for Apple Silicon, which were missing for Preview 1. After the <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-net-6-preview-1\/\">announcement of the overall .NET 6 release<\/a>, we&#8217;re now back to regularly scheduled monthly previews until the final release in November. You will see new features included in each preview that deliver on <a href=\"https:\/\/themesof.net\/\">.NET 6 themes, epics and user stories<\/a>. These themes offer improvements to every .NET application, including for server\/cloud, desktop, <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/blinking-leds-with-raspberry-pi\/\">IoT<\/a> and mobile.<\/p>\n<p>You can <a href=\"https:\/\/dotnet.microsoft.com\/download\/dotnet\/6.0\">download .NET 6 Preview 2<\/a>, for Windows, macOS, and Linux.<\/p>\n<ul>\n<li><a href=\"https:\/\/dotnet.microsoft.com\/download\/dotnet\/6.0\">Installers and binaries<\/a><\/li>\n<li><a href=\"https:\/\/hub.docker.com\/_\/microsoft-dotnet\">Container images<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/core\/blob\/main\/release-notes\/6.0\/\">Linux packages<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/core\/tree\/main\/release-notes\/6.0\">Release notes<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/core\/blob\/main\/release-notes\/6.0\/6.0-known-issues.md\">Known issues<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/dotnet\/core\/issues\/6057\">GitHub issue tracker<\/a><\/li>\n<\/ul>\n<p>See the <a href=\"https:\/\/devblogs.microsoft.com\/aspnet\/asp-net-core-updates-in-net-6-preview-2\">ASP.NET Core<\/a> and <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-entity-framework-core-6-0-preview-2\/\">EF Core<\/a> posts for more detail on what\u2019s new for web and data access scenarios.<\/p>\n<p>.NET 6 has been tested with Visual Studio 16.9 and Visual Studio for Mac 8.9. We recommend you use those builds if you want to try .NET 6.<\/p>\n<p>In this post, two of my team members will cover the <a href=\"https:\/\/themesof.net\/\">.NET 6 themes<\/a> that they are working on, specifically <a href=\"https:\/\/github.com\/dotnet\/core\/issues\/5510\">Improve inner-loop performance for .NET developers<\/a> and <a href=\"https:\/\/github.com\/dotnet\/core\/issues\/5423\">.NET has a great client app development experience<\/a>. I covered <a href=\"https:\/\/github.com\/dotnet\/core\/issues\/5491\">Improve startup and throughput using runtime execution information (PGO)<\/a> in the <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-net-6-preview-1\/#theme-improve-startup-and-throughput-using-runtime-execution-information-pgo\">.NET 6 Preview 1 post<\/a>.<\/p>\n<h2>Support<\/h2>\n<p>.NET 6 will be released in November 2021 and will be supported for three years, as a <a href=\"https:\/\/github.com\/dotnet\/core\/blob\/main\/release-policies.md\">Long Term Support (LTS) release<\/a>. The <a href=\"https:\/\/github.com\/dotnet\/core\/blob\/main\/release-notes\/6.0\/6.0-supported-os.md\">platform matrix<\/a> has been significantly expanded compared to .NET 5.<\/p>\n<p>The additions are:<\/p>\n<ul>\n<li>Android.<\/li>\n<li>iOS.<\/li>\n<li>Mac and Mac Catalyst, for x64 and Apple Silicon (AKA &#8220;M1&#8221;).<\/li>\n<li>Windows Arm64 (specifically Windows Desktop).<\/li>\n<\/ul>\n<p>.NET 6 Debian container images are based on Debian 11 (&#8220;bullseye&#8221;), which is <a href=\"https:\/\/wiki.debian.org\/DebianBullseye\">currently in testing<\/a>.<\/p>\n<h2>Theme &#8212; Improve .NET Inner Loop Performance<\/h2>\n<p><a href=\"https:\/\/github.com\/stephentoub\">Stephen Toub<\/a> is the author of this theme section. He&#8217;s part of the team working on the <a href=\"https:\/\/github.com\/dotnet\/core\/issues\/5510\">inner loop theme<\/a>, and is sharing his team&#8217;s goals and plans.<\/p>\n<p>Performance is top of mind for all .NET releases. Over the past several versions, a lot of effort has gone into improving throughput, reducing memory consumption, and other factors that impact the steady-state performance of an application. For .NET 6, we\u2019re also focused on a few additional aspects, several of which are highlighted as part of one of the .NET 6 themes: <a href=\"https:\/\/github.com\/dotnet\/core\/issues\/5510\">improving inner-loop performance for .NET developers<\/a>. Just as we\u2019ve focused on ensuring that apps and services have the best possible performance, we also want to ensure that developers are able to be as productive as possible, optimizing the tools and workflows that are frequently used as part of their \u201cinner loop\u201d (meaning the processes they use repeatedly as part of making code changes, building, and testing).<\/p>\n<p>Some of these efforts look very similar to traditional throughput efforts of the past, but instead of focusing on steady-state performance, they\u2019re focused on startup performance, of the runtimes, the app models, the <code>dotnet<\/code> CLI, MSBuild, etc., as well as the end-to-end performance of the tools (especially for smaller solutions, as historically they haven\u2019t received as much attention). The mindset involved in such optimizations is often quite different from the mindset used when optimizing for steady-state throughput. For steady-state work, you might focus on caching values that could be reused in the future, but often for startup performance you\u2019re focused on operations that may only be invoked once and where the costs for that first invocation matter. The work involved here does, however, look like many other performance efforts, with a typical profile-analyze-fix loop: you profile the relevant area of the application you want to optimize, you analyze the resulting data to look for the top offenders and bottlenecks, you come up with fixes for them, and then you start the process over to find the next impactful items. We\u2019re still early in the .NET 6 development cycle, but we\u2019ve already been successful in trimming overheads from key areas involved in developers\u2019 inner loops, focusing on various <code>dotnet<\/code> commands like <code>new<\/code>, <code>build<\/code>, and <code>run<\/code>. Example improvements thus far include fixing places tools were unexpectedly JIT\u2019ing (<a href=\"https:\/\/github.com\/dotnet\/installer\/pull\/9635\">dotnet\/installer #9635<\/a>), avoiding expensive logging-related work happening even when logging wasn\u2019t enabled (<a href=\"https:\/\/github.com\/dotnet\/aspnetcore\/pull\/27956\">dotnet\/aspnetcore #27956<\/a>), optimizing globbing in MSBuild (<a href=\"https:\/\/github.com\/dotnet\/msbuild\/pull\/6151\">dotnet\/msbuild #6151<\/a>), changing the ASP.NET Razor compiler to use a Roslyn source generator in order to avoid an extra compilation process (https:\/\/github.com\/dotnet\/sdk\/pull\/15756), and changing the .NET host to use file access patterns less likely to trigger antivirus tooling on the machine (<a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/48774\">dotnet\/runtime #48774<\/a>).<\/p>\n<p>Of course, one of the best performance optimizations is one that avoids the need for work to be done entirely, and that is the focus of the other half of this .NET 6 theme: .NET hot reload. Hot reload will improve developer productivity, across all supported operating systems and hardware platforms, by enabling code to be edited while an app is running, even without a debugger attached. With many kinds of edits, no restart will be required: the developer will save their changes, and the new version of the code will be applied to the executing process. Upon wanting to make a change to the app or service, rather than needing to stop it and go through the typical inner loop cycle of making the change, building, running, and getting back to the point in the app or service that triggered the need for the change in the first place, that whole cycle can be skipped for many kinds of edits. The work involved in enabling this spans the .NET release, requiring investments in the runtimes (both coreclr and mono), the C# Roslyn compiler, the app models (for example, Blazor, .NET MAUI), and the developer tools (for example, CLI, Visual Studio), but it is expected to fundamentally improve the way .NET developers go about writing their apps and services.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/03\/dotnet6-build-improvements.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-32292\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/03\/dotnet6-build-improvements.png\" alt=\"Image dotnet6 build improvements\" width=\"934\" height=\"518\" srcset=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/03\/dotnet6-build-improvements.png 934w, https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/03\/dotnet6-build-improvements-300x166.png 300w, https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2021\/03\/dotnet6-build-improvements-768x426.png 768w\" sizes=\"(max-width: 934px) 100vw, 934px\" \/><\/a><\/p>\n<p>The chart above demonstrates some early results of the inner loop effort.<\/p>\n<h2>Theme: .NET has a great client app development experience<\/h2>\n<p><a href=\"https:\/\/github.com\/maddyleger1\">Maddy Leger<\/a> is the author of this theme section. She is part of the team working on the <a href=\"https:\/\/github.com\/dotnet\/core\/issues\/5423\">client app development theme<\/a>, and is sharing her team&#8217;s goals and plans.<\/p>\n<p>One of the most exciting parts of .NET 6 is mobile development, which is currently offered as the separate Xamarin product. Over time, we&#8217;ve been making Xamarin more similar to mainline .NET. It&#8217;s now time to deliver a fully unified mobile product for .NET. With .NET 6, iOS, Android, and macOS development will be integrated into the .NET SDK experience and use the .NET libraries. For the past couple years, we\u2019ve been working to fold Mono into .NET, so developers can leverage the strengths of both runtimes without having to target different .NET versions or worry about compatibility issues. In .NET 5, we moved Blazor WebAssembly over, and are using that same model for Xamarin. .NET 6 is the culmination of this unification effort, encompassing a key Epic of the theme &#8211; <a href=\"https:\/\/github.com\/dotnet\/xamarin\/issues\/2\">Xamarin developers can upgrade to and use the latest .NET SDKs for their existing apps<\/a>.<\/p>\n<p>Now that all your .NET apps will run on the same libraries, we want to increase the amount of code you share across desktop and mobile platforms. Xamarin.Forms, Xamarin\u2019s cross-platform UI framework, is evolving into <a href=\"https:\/\/github.com\/dotnet\/maui\">.NET Multi-platform App UI<\/a>, enabling you to easily write apps for iOS, Android, Windows, and macOS with the same codebase. .NET MAUI is shipping as part of .NET 6 along with a bunch of performance and tooling improvements like .NET\/C# Hot Reload, more shared resources and code across different platforms, and better page rendering performance with a more flexible set of UI controls. You can follow the overall Epic: <a href=\"https:\/\/github.com\/dotnet\/xamarin\/issues\/21\">Xamarin\/.NET MAUI developers have improved app performance and share more code with .NET 6<\/a>.<\/p>\n<p>.NET MAUI isn\u2019t just for client app developers. Thanks to the refactored control set and the ability to run on the .NET 6 libraries, your existing Blazor apps will run natively on Windows and macOS via .NET MAUI. You\u2019ll be able to seamlessly weave in native controls and functionality alongside your Blazor codebase, including platform specific functionality. See the <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-net-6-preview-1\/#blazor-desktop-apps\">Preview 1 blog for some screenshots of \u201cBlazor desktop\u201d in action<\/a>.<\/p>\n<p>The final epic we\u2019re focused on in this theme is about packaging, deploying, and releasing your cross-platform client apps. Because there are so many developers\/target platforms\/ways to develop your apps, there are a lot of different app packages you have to distribute at the end of the day. Especially with Blazor desktop, we want to make that experience as seamless as possible. We\u2019re looking at strategies for improving release and versioning both locally and in the cloud as part of the epic Desktop developers can package, distribute, release, and update their applications to multiple desktop platforms and architectures.<\/p>\n<p>To summarize, in .NET 6 you\u2019ll be able to:<\/p>\n<ul>\n<li>Build iOS, Android, and macOS apps using the .NET libraries.<\/li>\n<li>Create iOS, Android, Windows, and macOS apps from the same codebase using .NET MAUI.<\/li>\n<li>Share more code and resources across platforms (such as images, app icons\/manifests, and more).<\/li>\n<li>Run your Blazor web apps natively on the macOS and Windows.<\/li>\n<li>Easily package and distribute your apps for all the target frameworks you include.<\/li>\n<\/ul>\n<p>We\u2019ve already made a lot of progress and will continue to add more features into each .NET 6 Preview. For more info, you can follow the <a href=\"http:\/\/github.com\/dotnet\/maui\">.NET MAUI repo<\/a>, which is kept up to date with progress reports.<\/p>\n<p>The remainder of the post is dedicated to features that are new in <a href=\"https:\/\/github.com\/dotnet\/core\/issues\/5889\">Preview 2<\/a>.<\/p>\n<h2>.NET Multi-platform App UI<\/h2>\n<p>We have added .NET MAUI and single project developer experiences for Android, iOS, and Mac Catalyst. We have updated our <a href=\"https:\/\/github.com\/dotnet\/net6-mobile-samples\">samples repository<\/a> with projects you can run today with .NET 6 Preview 2. As we progress through previews, more and more functionality will be enabled. Today your best experience running these projects is via the command line.<\/p>\n<h3>Mac Catalyst<\/h3>\n<p>You can add the following TargetFramework settings to your project to build for macOS desktop, using <a href=\"https:\/\/developer.apple.com\/mac-catalyst\/\">Mac Catalyst<\/a>.<\/p>\n<pre><code class=\"xml\">&lt;TargetFrameworks&gt;net6.0-android;net6.0-ios&lt;\/TargetFrameworks&gt;\r\n&lt;TargetFrameworks Condition=\" '$(OS)' != 'Windows_NT' \"&gt;$(TargetFrameworks);net6.0-maccatalyst&lt;\/TargetFrameworks&gt;\r\n<\/code><\/pre>\n<h3>A single, multi-targeted application project<\/h3>\n<p>We&#8217;ve now enabled a single project experience for .NET MAUI apps. You now get a very clean solution that can run on Android, iOS, and macOS. Windows support depends on WinUI 3 which is in its own preview now. We will add Windows to .NET MAUI in a future preview. See the <a href=\"https:\/\/github.com\/dotnet\/maui\/wiki\/Roadmap\">roadmap<\/a> for more details.<\/p>\n<p>To use this today, follow the guidance in our <a href=\"https:\/\/github.com\/dotnet\/net6-mobile-samples\">samples repository<\/a> to build and run from the command line. Future versions of Visual Studio will add device selections and run options.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/user-images.githubusercontent.com\/41873\/110378427-36651a80-801b-11eb-8707-ae3f7109ff16.png\" alt=\"single, multi-targeted application project\" \/><\/p>\n<h3>Shared fonts, images, and app icons<\/h3>\n<p>Fonts and images can be placed in one location in your solution and .NET MAUI will enable them to natively work on all platforms you target. These are tracked in your *.csproj as <code>SharedImage<\/code> and <code>SharedFont<\/code>.<\/p>\n<pre><code class=\"xml\">&lt;ItemGroup&gt;\r\n    &lt;SharedImage Include=\"appicon.svg\" ForegroundFile=\"appiconfg.svg\" IsAppIcon=\"true\" \/&gt;\r\n    &lt;SharedFont Include=\"Resources\\Fonts\\ionicons.ttf\" \/&gt;\r\n  &lt;\/ItemGroup&gt;\r\n<\/code><\/pre>\n<p>Both accept wildcards to include all files within a location.<\/p>\n<pre><code class=\"xml\">&lt;ItemGroup&gt;\r\n    &lt;SharedImage Include=\"appicon.svg\" ForegroundFile=\"appiconfg.svg\" IsAppIcon=\"true\" \/&gt;\r\n    &lt;SharedImage Include=\"Resources\\Images*\" \/&gt;\r\n    &lt;SharedFont Include=\"Resources\\Fonts*\" \/&gt;\r\n  &lt;\/ItemGroup&gt;\r\n<\/code><\/pre>\n<h3>MauiApp with Host Builder for bootstrapping your app<\/h3>\n<p>We have extensions for configuring services, fonts, and compatibility renderers for migrating Xamarin.Forms projects. <code>IWindow<\/code> has been introduced for multi-window support coming in a future release. This new pattern also introduces a single, consistent place for library authors and control vendors to integrate with .NET MAUI.<\/p>\n<pre><code class=\"csharp\">public class Application : MauiApp\r\n{\r\n    public override IAppHostBuilder CreateBuilder() =&gt; \r\n        base.CreateBuilder()\r\n            .RegisterCompatibilityRenderers()\r\n            .ConfigureServices((ctx, services) =&gt;\r\n            {\r\n                services.AddTransient&lt;MainPage&gt;();\r\n                services.AddTransient&lt;IWindow, MainWindow&gt;();\r\n            })\r\n            .ConfigureFonts((hostingContext, fonts) =&gt;\r\n            {\r\n                fonts.AddFont(\"ionicons.ttf\", \"IonIcons\");\r\n            });\r\n\r\n    public override IWindow CreateWindow(IActivationState state)\r\n    {\r\n        Microsoft.Maui.Controls.Compatibility.Forms.Init(state);\r\n        return Services.GetService&lt;IWindow&gt;();\r\n    }\r\n}\r\n<\/code><\/pre>\n<h3>New Control Handlers<\/h3>\n<p>We have introduced the first controls and properties that implement a new handler approach. These include partial implementations of Button, Label, and Entry, Slider, and Switch. We are now accepting pull requests to fill out complete implementations, and several contributors have already successfully contributed. For more information on joining the effort, visit the <a href=\"https:\/\/github.com\/dotnet\/maui\/wiki\/Handler-Property-PR-Guidelines\">handler property guidelines<\/a>.<\/p>\n<p>The <a href=\"https:\/\/github.com\/dotnet\/net6-mobile-samples\">HelloMaui sample application<\/a> now runs from a single project to macOS, iOS, and Android showcasing the current set of ported controls.<\/p>\n<p>macOS:\n<img decoding=\"async\" src=\"https:\/\/user-images.githubusercontent.com\/41873\/110378734-8d6aef80-801b-11eb-95fa-25155b9216ce.png\" alt=\"Screen Shot 2021-03-08 at 10 57 44 AM\" width=\"766\" \/><\/p>\n<p>iOS:\n<img decoding=\"async\" src=\"https:\/\/user-images.githubusercontent.com\/41873\/110379248-33b6f500-801c-11eb-8ef5-b0193d26a70e.png\" alt=\"Screen Shot 2021-03-08 at 2 39 34 PM\" width=\"502\" \/><\/p>\n<p>Android:\n<img decoding=\"async\" src=\"https:\/\/user-images.githubusercontent.com\/41873\/110379091-fce0df00-801b-11eb-9bf3-976174650f1b.png\" alt=\"Android emulator screenshot of .NET MAUI controls\" \/><\/p>\n<h3>Updates to Mobile SDKs<\/h3>\n<p>The mobile SDKs and surrounding tooling are gaining capabilities in this release as well. These capabilities will continue to improve as they are integrated with future Visual Studio releases.<\/p>\n<p><strong>Android:<\/strong><\/p>\n<ul>\n<li>Android X libraries are now available for .NET 6 and the default dependency for Android apps<\/li>\n<\/ul>\n<p><strong>iOS:<\/strong><\/p>\n<ul>\n<li>Developers on Windows can use the Remote iOS Simulator<\/li>\n<li>Developers on Windows can connect to the remote Mac build host<\/li>\n<li>Ahead-of-time compilation has been added to enables building and deploying to physical iOS hardware<\/li>\n<\/ul>\n<h2>.NET Libraries<\/h2>\n<p>The following APIs and improvements have been added to the .NET libraries.<\/p>\n<h3>System.Text.Json &#8211; ReferenceHandler.IgnoreCycles<\/h3>\n<p><a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/system.text.json.jsonserializer\"><code>JsonSerializer<\/code> (System.Text.Json)<\/a> now supports the ability to <a href=\"https:\/\/github.com\/dotnet\/runtime\/issues\/40099\">ignore cycles when serializing an object graph<\/a>. The <code>ReferenceHandler.IgnoreCycles<\/code> option has similar behavior as Newtonsoft.Json <a href=\"https:\/\/www.newtonsoft.com\/json\/help\/html\/ReferenceLoopHandlingIgnore.htm\"><code>ReferenceLoopHandling.Ignore<\/code><\/a>. One key difference is that the System.Text.Json implementation replaces reference loops with the <code>null<\/code> JSON token instead of ignoring the object reference.<\/p>\n<p>You can see the behavior of <code>ReferenceHandler.IgnoreCycles<\/code> in the following example. In this case, the <code>Next<\/code> property is serialized as <code>null<\/code> since it otherwise creates a cycle.<\/p>\n<pre><code class=\"csharp\">class Node\r\n{\r\n    public string Description { get; set; }\r\n    public object Next { get; set; }\r\n}\r\n\r\nvoid Test()\r\n{\r\n    var node = new Node { Description = \"Node 1\" };\r\n    node.Next = node;\r\n\r\n    var opts = new JsonSerializerOptions { ReferenceHandler = ReferenceHandler.IgnoreCycles };\r\n\r\n    string json = JsonSerializer.Serialize(node, opts);\r\n    Console.WriteLine(json); \/\/ Prints {\"Description\":\"Node 1\",\"Next\":null}\r\n}\r\n<\/code><\/pre>\n<h3>PriorityQueue<\/h3>\n<p><code>PriorityQueue&lt;TElement, TPriority&gt;<\/code> (System.Collections.Generic) is a new collection that enables adding new items with a value and a priority. On dequeue the PriorityQueue returns the element with the lowest priority value. You can think of this new collection as similar to <code>Queue&lt;T&gt;<\/code> but that each enqueued element has a priority value that affects the behavior of dequeue.<\/p>\n<p>The following sample demonstrates the behavior of <code>PriorityQueue&lt;string, int&gt;<\/code>.<\/p>\n<pre><code class=\"csharp\">\/\/ creates a priority queue of strings with integer priorities\r\nvar pq = new PriorityQueue&lt;string, int&gt;();\r\n\r\n\/\/ enqueue elements with associated priorities\r\npq.Enqueue(\"A\", 3);\r\npq.Enqueue(\"B\", 1);\r\npq.Enqueue(\"C\", 2);\r\npq.Enqueue(\"D\", 3);\r\n\r\npq.Dequeue(); \/\/ returns \"B\"\r\npq.Dequeue(); \/\/ returns \"C\"\r\npq.Dequeue(); \/\/ either \"A\" or \"D\", stability is not guaranteed.\r\n<\/code><\/pre>\n<p>Credit to community member <a href=\"https:\/\/github.com\/pgolebiowski\">Patryk Golebiowski<\/a> for contributing <a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/46009\">the implementation<\/a>.<\/p>\n<h3>Better parsing of standard numeric formats<\/h3>\n<p>We&#8217;ve improved the parser for the standard numeric types, specifically for <code>.ToString<\/code> and <code>.TryFormat<\/code>. They will provide better results when precision &gt; 99 decimal places is specified. Also, the parser now better supports trailing zeros in the <code>Parse<\/code> method.<\/p>\n<p>The following examples demonstrate before and after behavior.<\/p>\n<ul>\n<li><code>32.ToString(\"C100\")<\/code> -&gt; <code>C132<\/code>\n<ul>\n<li>.NET 6: <code>$32.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000<\/code><\/li>\n<li>.NET 5: We had an artificial limitation in the formatting code to only handle a precision of &lt;= 99. For precision &gt;= 100, we instead interpreted the input as a custom format.<\/li>\n<\/ul>\n<\/li>\n<li><code>32.ToString(\"H99\")<\/code> -&gt; throw a <code>FormatException<\/code>\n<ul>\n<li>.NET 6: throws a FormatException<\/li>\n<li>This is correct behavior, but it&#8217;s called here to contrast with the next example.<\/li>\n<\/ul>\n<\/li>\n<li><code>32.ToString(\"H100\")<\/code> -&gt; <code>H132<\/code>\n<ul>\n<li>.NET 6: throw a FormatException<\/li>\n<li>.NET 5: <code>H<\/code> is an invalid format specifier. So, we should&#8217;ve thrown a <code>FormatException<\/code>. Instead, our incorrect behavior of interpreting precision &gt;= 100 as custom formats meant we returned wrong values.<\/li>\n<\/ul>\n<\/li>\n<li><code>double.Parse(\"9007199254740997.0\")<\/code> -&gt; <code>9007199254740998<\/code>\n<ul>\n<li>.NET 6: <code>9007199254740996<\/code>.<\/li>\n<li>.NET 5: <code>9007199254740997.0<\/code> is not exactly representable in the IEEE 754 format. With our current rounding scheme, the correct return value should have been <code>9007199254740996<\/code>. However, the last <code>.0<\/code> portion of the input was forcing the parser to incorrectly round the result and return <code>9007199254740998<\/code>.<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p>Changes:<\/p>\n<ul>\n<li>https:\/\/github.com\/dotnet\/runtime\/issues\/46827<\/li>\n<li>https:\/\/github.com\/dotnet\/docs\/pull\/23046<\/li>\n<li>https:\/\/github.com\/dotnet\/docs\/issues\/22458<\/li>\n<\/ul>\n<h3>SignalR &#8211; Nullable annotations<\/h3>\n<p>The <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.AspNetCore.SignalR.Client\/\">ASP.NET Core SignalR Client<\/a> package has been <a href=\"https:\/\/github.com\/dotnet\/aspnetcore\/pull\/29219\">annotated for nullability<\/a>. This means that the C# compiler will provide appropriate feedback, when you <a href=\"https:\/\/docs.microsoft.com\/dotnet\/csharp\/language-reference\/builtin-types\/nullable-value-types\">enable nullability<\/a>, based on your handling of nulls in SignalR APIs. The SignalR server has already been updated for nullability in 5.0, but a few modifications were made in 6.0. You can track ASP.NET Core support for nullable annotations at <a href=\"https:\/\/github.com\/dotnet\/aspnetcore\/issues\/27389\">dotnet\/aspnetcore #27389<\/a>.<\/p>\n<p>Nullable annotations were a big focus of the .NET Core 3.x and .NET 5 releases. All of the .NET libraries (AKA &#8220;base class libraries&#8221;) were annotated as part of those releases. The <a href=\"https:\/\/www.nuget.org\/packages\/System.Device.Gpio\/\">System.Device.Gpio<\/a> package was also annotated as part of the .NET 5 release.<\/p>\n<p>You need to add <code>&lt;Nullable&gt;enable&lt;\/Nullable&gt;<\/code> in your project file to use the nullable annotations.<\/p>\n<h2>Runtime<\/h2>\n<p>The following improvements have been made in (or related to) the .NET runtime.<\/p>\n<h3>Framework Assemblies are compiled with Crossgen2<\/h3>\n<p>Update: This change (compiling more assemblies with crossgen2) didn&#8217;t make it into Preview 2, but will be part of Preview 3.<\/p>\n<p>All of the .NET libraries are now compiled with <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-net-6-preview-1\/#crossgen2\">crossgen 2<\/a>, across all supported operating systems and architectures. This includes all libraries in the <code>Microsoft.NETCore.App<\/code> directory, but not the other frameworks, such as ASP.NET or Windows Desktop. Those frameworks will be transitioned to crossgen 2 in Previews 3 and\/or 4.<\/p>\n<p>Crossgen 2 itself isn&#8217;t intended to improve performance. As I said in the <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-net-6-preview-1\/#crossgen2\">preview 1 post<\/a>, the purpose of Crossgen 2 is to enable new performance features like <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-net-6-preview-1\/#theme-improve-startup-and-throughput-using-runtime-execution-information-pgo\">PGO<\/a>. That said, Crossgen 2 has delivered modest size-on-disk improvements based on some targeted size optimizations, as you can see in the following comparison. Main point is that moving to Crossgen 2 does not incur any up-front regressions. It is effectively neutral, as promised.<\/p>\n<pre><code class=\"console\">Size [MB] FullName\r\n--------- --------\r\n64.22     C:Program FilesdotnetsharedMicrosoft.NETCore.App5.0.3\r\n63.31     C:Program FilesdotnetsharedMicrosoft.NETCore.App6.0.0-preview.1.21102.12\r\n63.00     C:Program FilesdotnetsharedMicrosoft.NETCore.App6.0.0-preview.2.21118.6\r\n<\/code><\/pre>\n<h3>Profile guided optimization<\/h3>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-net-6-preview-1\/#theme-improve-startup-and-throughput-using-runtime-execution-information-pgo\">Profile guided optimization<\/a> enables us to generate code that is optimal based on a variety of characteristics. We are building both static and <a href=\"https:\/\/github.com\/dotnet\/runtime\/issues\/43618\">dynamic PGO<\/a> variations.<\/p>\n<p>The following improvements have been made in Preview 2:<\/p>\n<ul>\n<li>Allow CSE &amp; hoisting of vtable lookups for the indirections &#8212; <a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/47808\">dotnet\/runtime #47808<\/a><\/li>\n<li>Block counts in tiered compilation &#8212; <a href=\"https:\/\/github.com\/dotnet\/runtime\/issues\/13672\">dotnet\/runtime #13672<\/a><\/li>\n<li>Allow Inlinee profile scale-up &#8212; <a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/48280\">dotnet\/runtime #48280<\/a><\/li>\n<li>Efficient profiling scheme (e.g., spanning tree with efficient edge instrumentation) &#8212; <a href=\"https:\/\/github.com\/dotnet\/runtime\/issues\/46882\">dotnet\/runtime #46882<\/a>, <a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/47509\">dotnet\/runtime #47509<\/a>, <a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/47476\">dotnet\/runtime #47476<\/a>, <a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/47072\">dotnet\/runtime #47072<\/a>, <a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/47597\">dotnet\/runtime #47597<\/a>, <a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/47723\">dotnet\/runtime #47723<\/a>, <a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/47876\">dotnet\/runtime #47876<\/a>, <a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/47959\">dotnet\/runtime #47959<\/a><\/li>\n<\/ul>\n<h3>JIT improvements<\/h3>\n<p>The following improvements were made to optimize the code generated by the JIT.<\/p>\n<ul>\n<li>Not aligning cloned loops &#8212; <a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/48090\">dotnet\/runtime #48090<\/a><\/li>\n<li>MultiplyHigh intrinsics (<code>smulh<\/code>\/<code>umulh<\/code>) &#8212; <a href=\"https:\/\/github.com\/dotnet\/runtime\/pull\/47362\">dotnet\/runtime #47362<\/a><\/li>\n<\/ul>\n<p>The first improvement is the latest result of a project to <a href=\"https:\/\/github.com\/dotnet\/runtime\/issues\/43227\">stabilize performance measurements<\/a>. You can read recent analyses (<a href=\"https:\/\/github.com\/dotnet\/runtime\/issues\/43227#issuecomment-767967603\">January 26, 2021<\/a>; <a href=\"https:\/\/github.com\/dotnet\/runtime\/issues\/43227#issuecomment-772914110\">February 3, 2021<\/a>) that provide an in-depth explanation of our progress.<\/p>\n<p>The second improvement is specific to Arm64. We continue to <a href=\"https:\/\/github.com\/dotnet\/runtime\/issues\/43629\">improve the performance of the code that the JIT generates for Arm64<\/a>, in collaboration with Arm engineers.<\/p>\n<h2>Closing<\/h2>\n<p>We&#8217;re back to the regular monthly previews, with .NET 6. Please give .NET 6 Preview 2 a spin in your environment, in a <a href=\"https:\/\/hub.docker.com\/_\/microsoft-dotnet-sdk\">container<\/a>, a virtual machine or on a test machine. We want your feedback to help us improve these new features before we release the final version in November. We expect that the majority of the release should be done by July; we&#8217;ll focus on quality after that. That gives you a sense of the windows we have for feedback. The earlier you can give feedback, the better.<\/p>\n<p>You can expect to see more in <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-net-6-preview-1\">.NET 6<\/a> for <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-net-6-preview-1\/#net-multi-platform-app-ui\">mobile<\/a> and <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-net-6-preview-1\/#blazor-desktop-apps\">Blazor Desktop<\/a> in subsequent previews. We&#8217;re still in the process of building those features.<\/p>\n<div class=\"ms-editor-squiggler\" style=\"color: initial; font: initial; font-feature-settings: initial; font-kerning: initial; font-optical-sizing: initial; font-variation-settings: initial; forced-color-adjust: initial; text-orientation: initial; text-rendering: initial; -webkit-font-smoothing: initial; -webkit-locale: initial; -webkit-text-orientation: initial; -webkit-writing-mode: initial; writing-mode: initial; zoom: initial; place-content: initial; place-items: initial; place-self: initial; alignment-baseline: initial; animation: initial; appearance: initial; aspect-ratio: initial; backdrop-filter: initial; backface-visibility: initial; background: initial; background-blend-mode: initial; baseline-shift: initial; block-size: initial; border-block: initial; border: initial; border-radius: initial; border-collapse: initial; border-end-end-radius: initial; border-end-start-radius: initial; border-inline: initial; border-start-end-radius: initial; border-start-start-radius: initial; inset: initial; box-shadow: initial; box-sizing: initial; break-after: initial; break-before: initial; break-inside: initial; buffered-rendering: initial; caption-side: initial; caret-color: initial; clear: initial; clip: initial; clip-path: initial; clip-rule: initial; color-interpolation: initial; color-interpolation-filters: initial; color-rendering: initial; color-scheme: initial; columns: initial; column-fill: initial; gap: initial; column-rule: initial; column-span: initial; contain: initial; contain-intrinsic-size: initial; content: initial; content-visibility: initial; counter-increment: initial; counter-reset: initial; counter-set: initial; cursor: initial; cx: initial; cy: initial; d: initial; display: block; dominant-baseline: initial; empty-cells: initial; fill: initial; fill-opacity: initial; fill-rule: initial; filter: initial; flex: initial; flex-flow: initial; float: initial; flood-color: initial; flood-opacity: initial; grid: initial; grid-area: initial; height: 0px; hyphens: initial; image-orientation: initial; image-rendering: initial; inline-size: initial; inset-block: initial; inset-inline: initial; isolation: initial; letter-spacing: initial; lighting-color: initial; line-break: initial; list-style: initial; margin-block: initial; margin: initial; margin-inline: initial; marker: initial; mask: initial; mask-type: initial; max-block-size: initial; max-height: initial; max-inline-size: initial; max-width: initial; min-block-size: initial; min-height: initial; min-inline-size: initial; min-width: initial; mix-blend-mode: initial; object-fit: initial; object-position: initial; offset: initial; opacity: initial; order: initial; origin-trial-test-property: initial; orphans: initial; outline: initial; outline-offset: initial; overflow-anchor: initial; overflow-wrap: initial; overflow: initial; overscroll-behavior-block: initial; overscroll-behavior-inline: initial; overscroll-behavior: initial; padding-block: initial; padding: initial; padding-inline: initial; page: initial; page-orientation: initial; paint-order: initial; perspective: initial; perspective-origin: initial; pointer-events: initial; position: initial; quotes: initial; r: initial; resize: initial; ruby-position: initial; rx: initial; ry: initial; scroll-behavior: initial; scroll-margin-block: initial; scroll-margin: initial; scroll-margin-inline: initial; scroll-padding-block: initial; scroll-padding: initial; scroll-padding-inline: initial; scroll-snap-align: initial; scroll-snap-stop: initial; scroll-snap-type: initial; shape-image-threshold: initial; shape-margin: initial; shape-outside: initial; shape-rendering: initial; size: initial; speak: initial; stop-color: initial; stop-opacity: initial; stroke: initial; stroke-dasharray: initial; stroke-dashoffset: initial; stroke-linecap: initial; stroke-linejoin: initial; stroke-miterlimit: initial; stroke-opacity: initial; stroke-width: initial; tab-size: initial; table-layout: initial; text-align: initial; text-align-last: initial; text-anchor: initial; text-combine-upright: initial; text-decoration: initial; text-decoration-skip-ink: initial; text-indent: initial; text-overflow: initial; text-shadow: initial; text-size-adjust: initial; text-transform: initial; text-underline-offset: initial; text-underline-position: initial; touch-action: initial; transform: initial; transform-box: initial; transform-origin: initial; transform-style: initial; transition: initial; user-select: initial; vector-effect: initial; vertical-align: initial; visibility: initial; -webkit-app-region: initial; border-spacing: initial; -webkit-border-image: initial; -webkit-box-align: initial; -webkit-box-decoration-break: initial; -webkit-box-direction: initial; -webkit-box-flex: initial; -webkit-box-ordinal-group: initial; -webkit-box-orient: initial; -webkit-box-pack: initial; -webkit-box-reflect: initial; -webkit-highlight: initial; -webkit-hyphenate-character: initial; -webkit-line-break: initial; -webkit-line-clamp: initial; -webkit-mask-box-image: initial; -webkit-mask: initial; -webkit-mask-composite: initial; -webkit-perspective-origin-x: initial; -webkit-perspective-origin-y: initial; -webkit-print-color-adjust: initial; -webkit-rtl-ordering: initial; -webkit-ruby-position: initial; -webkit-tap-highlight-color: initial; -webkit-text-combine: initial; -webkit-text-decorations-in-effect: initial; -webkit-text-emphasis: initial; -webkit-text-emphasis-position: initial; -webkit-text-fill-color: initial; -webkit-text-security: initial; -webkit-text-stroke: initial; -webkit-transform-origin-x: initial; -webkit-transform-origin-y: initial; -webkit-transform-origin-z: initial; -webkit-user-drag: initial; -webkit-user-modify: initial; white-space: initial; widows: initial; width: initial; will-change: initial; word-break: initial; word-spacing: initial; x: initial; y: initial; z-index: initial;\"><\/div>\n","protected":false},"excerpt":{"rendered":"<p>.NET 6 Preview 2 is now available.<\/p>\n","protected":false},"author":1312,"featured_media":30458,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685,196],"tags":[4],"class_list":["post-32255","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-dotnet-core","tag-net"],"acf":[],"blog_post_summary":"<p>.NET 6 Preview 2 is now available.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/32255","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/1312"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=32255"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/32255\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/30458"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=32255"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=32255"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=32255"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}