{"id":43033,"date":"2022-11-04T08:05:00","date_gmt":"2022-11-04T15:05:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=43033"},"modified":"2024-12-13T14:20:23","modified_gmt":"2024-12-13T22:20:23","slug":"announcing-dotnet-community-toolkit-v810-preview-1","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-dotnet-community-toolkit-v810-preview-1\/","title":{"rendered":"Announcing .NET Community Toolkit v8.1.0 Preview 1"},"content":{"rendered":"<p>We&#8217;re happy to announce Preview 1 of the upcoming .NET Community Toolkit 8.1 release! This first official preview includes several highly requested new features, bug fixes, and most importantly it includes <strong>massive<\/strong> performance improvements to the MVVM Toolkit source generators, to make the developer UX when using them even in very large solutions, better than ever!<\/p>\n<p><a href=\"https:\/\/aka.ms\/toolkit\/dotnet\/\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/dotnet\/wp-content\/uploads\/sites\/10\/2022\/10\/NCT-1920x1080-1.png\" alt=\".NET Community Toolkit 8.1.0 Preview 1\" \/><\/a><\/p>\n<p>Just like for all our previous releases, we&#8217;ve put a lot of effort into listening to feedback received both by teams here at Microsoft using the Toolkit, as well as other developers in the community, and that feedback has helped shape all the new changes in the .NET Community Toolkit. We\u2019re really thankful to everyone that has contributed and that keeps helping the .NET Community Toolkit get better every day! \ud83c\udf89<\/p>\n<h2>What&#8217;s in the .NET Community Toolkit? \ud83d\udc40<\/h2>\n<p>Just to give a brief summary of what the .NET Community Toolkit includes, here&#8217;s the libraries it consists of:<\/p>\n<ul>\n<li><code>CommunityToolkit.Common<\/code><\/li>\n<li><code>CommunityToolkit.Mvvm<\/code> (aka \u201cMicrosoft MVVM Toolkit\u201d)<\/li>\n<li><code>CommunityToolkit.Diagnostics<\/code><\/li>\n<li><code>CommunityToolkit.HighPerformance<\/code><\/li>\n<\/ul>\n<p>The libraries are also widely used in some inbox apps that ship with Windows, such as the Microsoft Store! \ud83d\ude80<\/p>\n<blockquote><p>For more details on the history of the .NET Community Toolkit, <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/announcing-the-dotnet-community-toolkit-800\/\">here is a link to our previous 8.0.0 announcement post<\/a>.<\/p><\/blockquote>\n<p>Here is a breakdown of the main changes you can expect in this new release.<\/p>\n<h2>Custom attributes for <code>[ObservableProperty]<\/code> \ud83e\udd16<\/h2>\n<p>One of the <a href=\"https:\/\/github.com\/CommunityToolkit\/dotnet\/issues\/413\">most requested features<\/a> (see <a href=\"https:\/\/github.com\/CommunityToolkit\/dotnet\/issues\/208\">#208<\/a>, <a href=\"https:\/\/github.com\/CommunityToolkit\/dotnet\/discussions\/217\">#217<\/a>, <a href=\"https:\/\/github.com\/CommunityToolkit\/dotnet\/discussions\/228\">#228<\/a>) for the MVVM Toolkit source generator was to support using custom attributes for <code>[ObservableProperty]<\/code>. There were several proposed designs to support this, and we eventually decided to leverage the existing <code>property:<\/code> syntax in C# to let developers mark attributes to propagate to generated properties. This gives us several advantages:<\/p>\n<ul>\n<li>It leverages built-in C# syntax, making the feature feel &#8220;native&#8221; and without needing extra attributes<\/li>\n<li>It solves the issue of annotating attributes that can only target properties and not fields<\/li>\n<\/ul>\n<p>That is, with the MVVM Toolkit 8.1, the following scenario is now supported:<\/p>\n<pre><code class=\"language-csharp\">[ObservableProperty]\r\n[property: JsonPropertyName(\"responseName\")]\r\n[property: JsonRequired]\r\nprivate string? _name;<\/code><\/pre>\n<p>This will then generate the following property behind the scenes:<\/p>\n<pre><code class=\"language-csharp\">[JsonPropertyName(\"responseName\")]\r\n[JsonRequired]\r\npublic string? Name\r\n{\r\n    get =&gt; _name;\r\n    set\r\n    {\r\n        if (!EqualityComparer&lt;string?&gt;.Default.Equals(_name, value))\r\n        {\r\n            OnPropertyChanging(\"Name\");\r\n            OnNameChanging(value);\r\n\r\n            _name = value;\r\n\r\n            OnPropertyChanged(\"Name\");\r\n            OnNameChanged(value);\r\n        }\r\n    }\r\n}\r\n\r\npartial void OnNameChanging(string? value);\r\npartial void OnNameChanged(string? value);<\/code><\/pre>\n<p>You can see how the generated property has the two attributes we specified! This allows complete flexibility in annotations for generated properties, all while using built-in C# syntax and with no constraints on the types of attributes that this features supports \ud83d\ude4c<\/p>\n<blockquote><p>Note: the generated code is slightly different and includes additional performance optimizations not shown here.<\/p>\n<p>You can find all of our docs on the new source generators <a href=\"https:\/\/learn.microsoft.com\/dotnet\/communitytoolkit\/mvvm\/generators\/overview\">here<\/a>, and if you prefer a video version, <a href=\"https:\/\/twitter.com\/JamesMontemagno\">James Montemagno<\/a> has also done several videos on them, such as <a href=\"https:\/\/www.youtube.com\/watch?v=AXpTeiWtbC8&amp;t=600s\">this one<\/a>.<\/p><\/blockquote>\n<h2>MVVM Toolkit source generator optimizations \ud83d\udeeb<\/h2>\n<p>As we mentioned, this new preview release also includes major performance optimizations to the MVVM Toolkit, to improve the developer UX even more especially when working on very large solutions. We spent a lot of time improving the architecture of all our generators and talking with engineers from the Roslyn team to make sure that we were doing everything possible to squeeze as much performance out of them as we could.<\/p>\n<p>Here&#8217;s just some of the improvements on this front:<\/p>\n<ul>\n<li><strong>Added multi-targeting for Roslyn 4.3<\/strong> (<a href=\"https:\/\/github.com\/CommunityToolkit\/dotnet\/pull\/428\">#428<\/a>, <a href=\"https:\/\/github.com\/CommunityToolkit\/dotnet\/pull\/462\">#462<\/a>): the MVVM Toolkit source generators will now use the Roslyn 4.3 target if supported, so that they can opt-in into some more optimized APIs if the host supports it. This is automatically enabled when referencing the MVVM Toolkit.<\/li>\n<li><strong>Used <code>ForAttributeWithMetadataName&lt;T&gt;<\/code><\/strong> (<a href=\"https:\/\/github.com\/CommunityToolkit\/dotnet\/pull\/436\">#436<\/a>): we switched the generators to the new <a href=\"https:\/\/github.com\/dotnet\/roslyn\/issues\/54725\">high-level Roslyn API to match attributes<\/a>, which greatly improves performance for generators triggering over specific attributes. For instance, <code>[ObservableProperty]<\/code> is now using this.<\/li>\n<li><strong>Moved diagnostics to diagnostic analyzers<\/strong> (<a href=\"https:\/\/github.com\/CommunityToolkit\/dotnet\/pull\/433\">#433<\/a>, <a href=\"https:\/\/github.com\/CommunityToolkit\/dotnet\/pull\/434\">#434<\/a>): we moved almost all diagnostics to diagnostics analyzers, which are run out of process and independently from source generators. This significantly reduces overhead when typing, as all the logic for the diagnostics is now run in a separate process and cannot slow IntelliSense down.<\/li>\n<li><strong>Stopped using symbols in incremental providers<\/strong> (<a href=\"https:\/\/github.com\/CommunityToolkit\/dotnet\/pull\/435\">#435<\/a>): we updated all our incremental providers to no longer propagate symbols. This can reduce memory use, as propagating symbols can cause Roslyn to unnecessarily root compilation objects.<\/li>\n<li><strong>More performance optimizations<\/strong> (<a href=\"https:\/\/github.com\/CommunityToolkit\/dotnet\/pull\/447\">#447<\/a>, <a href=\"https:\/\/github.com\/CommunityToolkit\/dotnet\/pull\/460\">#460<\/a>, <a href=\"https:\/\/github.com\/CommunityToolkit\/dotnet\/pull\/469\">#469<\/a>, <a href=\"https:\/\/github.com\/CommunityToolkit\/dotnet\/pull\/487\">#487<\/a>, <a href=\"https:\/\/github.com\/CommunityToolkit\/dotnet\/pull\/489\">#489<\/a>): we overhauled all our incremental models and incremental pipelines to significantly improve performance and reduce memory allocations.<\/li>\n<\/ul>\n<h2><code>IObservable&lt;T&gt;<\/code> messenger extensions \ud83d\udceb<\/h2>\n<p>Another requested feature, especially by developers heavily using Reactive-style APIs in their applications, was to have a way to bridge the functionality exposed by the <a href=\"https:\/\/learn.microsoft.com\/dotnet\/communitytoolkit\/mvvm\/messenger\">messenger APIs<\/a> in the MVVM Toolkit. This is now supported, thanks to the new <a href=\"https:\/\/github.com\/CommunityToolkit\/dotnet\/issues\/408\"><code>IObservable&lt;T&gt;<\/code> extensions<\/a> for the <code>IMessenger<\/code> interface. You can use them as follows:<\/p>\n<pre><code class=\"language-csharp\">IObservable&lt;MyMessage&gt; observable = Messenger.CreateObservable&lt;MyMessage&gt;();<\/code><\/pre>\n<p>&#8230;That&#8217;s it! This extension will create an <code>IObservable&lt;T&gt;<\/code> object that can be used to subscribe to messages and dynamically react to them. Specifying different tokens is also supported, through a separate overloads. Here is another example showing an end-to-end use of the new API:<\/p>\n<pre><code class=\"language-csharp\">var token =\r\n    Messenger\r\n    .CreateObservable&lt;MyMessage&gt;()\r\n    .Where(...)\r\n    .Subscribe(m =&gt; Console.WriteLine($\"Hello {m.Username}!\"));<\/code><\/pre>\n<h2>.NET 7 and C# 11 support \ud83d\ude80<\/h2>\n<p>This new preview release of the .NET Community Toolkit also adds the .NET 7 TFM to the HighPerformance package, and includes several changes to benefit from the new C# 11 language features, specifically <a href=\"https:\/\/github.com\/dotnet\/csharplang\/blob\/main\/proposals\/csharp-11.0\/low-level-struct-improvements.md\"><code>ref<\/code> fields<\/a>.<\/p>\n<p>The following types are now no longer in preview, and have been updated to leverage the new <code>ref<\/code> safety rules:<\/p>\n<ul>\n<li><code>Ref&lt;T&gt;<\/code><\/li>\n<li><code>ReadOnlyRef&lt;T&gt;<\/code><\/li>\n<li><code>NullableRef&lt;T&gt;<\/code><\/li>\n<li><code>ReadOnlyNullableRef&lt;T&gt;<\/code><\/li>\n<\/ul>\n<p>An example of where these can be used is as follows:<\/p>\n<pre><code class=\"language-csharp\">public static bool TryGetElementRef(out NullableRef&lt;T&gt; reference)\r\n{\r\n    \/\/ Logic here...\r\n}<\/code><\/pre>\n<p>That is, the <code>NullableRef&lt;T&gt;<\/code> type effectively enables a method to have an <code>out ref T<\/code> parameter, which is not otherwise expressible in C#. We also plan to extend the API surface of these types in the future to allow these types to provide an easy to use alternative to GC-ref arithmetic using the <code>Unsafe<\/code> type, which can also be visually more similar to traditional pointer arithmetic.<\/p>\n<h2>Other changes \u2699\ufe0f<\/h2>\n<p>There is much more being included in this new release!<\/p>\n<p>You can see the full changelog in the <a href=\"https:\/\/github.com\/CommunityToolkit\/dotnet\/releases\/tag\/v8.1.0-preview1\">GitHub release page<\/a>.<\/p>\n<h2>Get started today! \ud83c\udf89<\/h2>\n<p>You can find all source code in our <a href=\"https:\/\/aka.ms\/toolkit\/dotnet\/\">GitHub repo<\/a>, some handwritten docs on <a href=\"https:\/\/aka.ms\/toolkit\/docs\/\">MS learn<\/a>, and complete API references in the .NET API browser website. If you would like to contribute, feel free to open issues or to reach out to let us know about your experience! To follow the conversation on Twitter, use the #CommunityToolkit hashtag. All your feedbacks greatly help in shape the direction of these libraries, so make sure to share them!<\/p>\n<h2>More resources \ud83c\udf9e\ufe0f<\/h2>\n<p>If you want to learn more about the MVVM Toolkit, you can also check out this video from the last <a href=\"https:\/\/devblogs.microsoft.com\/dotnet\/dotnet-conf-focus-on-maui-recap\/\">.NET Conf Focus on MAUI<\/a> event earlier this year, that showcases how you can use the MVVM Toolkit and all the new source generator features to build a MAUI application:<\/p>\n<p><iframe width=\"560\" height=\"315\" src=\"https:\/\/www.youtube.com\/embed\/OP9g5dM0bgk\" allowfullscreen><\/iframe><\/p>\n<p>There&#8217;s a whole ecosystem of Toolkit-s that are available, with tons of useful APIs to build .NET applications! Tune in to the upcoming <a href=\"https:\/\/www.dotnetconf.net\/\">.NET Conf 2022<\/a> to discover more!<\/p>\n<p>Happy coding! \ud83d\udcbb<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We\u2019re happy to announce the first preview of the upcoming .NET Community Toolkit 8.1 release is now live, bringing with it some new highly requested features and major performance optimizations to the MVVM Toolkit source generators!<\/p>\n","protected":false},"author":81469,"featured_media":43034,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685,195,7233,756,3009,509,489],"tags":[7238,7655,51,7654,58,63,100,7243],"class_list":["post-43033","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-dotnet-framework","category-maui","category-csharp","category-performance","category-wpf","category-xaml","tag-net-maui","tag-net-maui-community-toolkit","tag-community","tag-community-toolkit","tag-csharp","tag-dotnet","tag-mvvm","tag-toolkit"],"acf":[],"blog_post_summary":"<p>We\u2019re happy to announce the first preview of the upcoming .NET Community Toolkit 8.1 release is now live, bringing with it some new highly requested features and major performance optimizations to the MVVM Toolkit source generators!<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/43033","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\/81469"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=43033"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/43033\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/43034"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=43033"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=43033"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=43033"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}