NET 9 is the latest iteration of Microsoft's cross-platform framework, designed to enhance modern application development with a focus on performance, security, and ease of use. This new version brings significant updates to its runtime, libraries, SDK, and related tools, as well as introducing advanced features for AI-based development, web, and mobile applications.
If you’re a developer looking to stay updated on all the latest features, this article breaks down every update in .NET 9 so you can make the most of this powerful platform.
1. .NET Runtime: Enhancing the Core of the Framework
The .NET 9 runtime has been optimized to deliver superior performance, improve the developer experience, and ensure applications are more efficient and robust. If you work with applications that demand high performance, these updates will be of particular interest.
1.1. Garbage Collector (GC) Optimization
The Garbage Collector in .NET 9 continues to evolve, with a focus on reducing pauses during collection in high-memory pressure scenarios. If you've ever dealt with micro-stutters in your applications when processing large volumes of data, this update is a relief.
For example, if you have an application that generates large amounts of temporary objects, the GC is now smarter about prioritizing what to collect and when.
How does this translate in practice?
Previously, in applications with massive lists, the GC could cause noticeable interruptions. Now, these interruptions are significantly reduced thanks to improved compaction and reduced costs associated with promoting objects between generations.
A look at the code:
var data = Enumerable.Range(1, 10_000_000).ToList();
Console.WriteLine($"Processing {data.Count} items...");
data = null; // Release memory.
GC.Collect(); // Manually invoke the collector.
In this example, the process of freeing and collecting memory is faster in .NET 9, especially in systems with intensive memory usage.
1.2. ARM64 Support
With the growing adoption of ARM64 in servers and devices, .NET 9 introduces specific optimizations for this architecture. This not only improves performance on ARM devices like the Raspberry Pi but also on modern servers using ARM for greater energy efficiency.
What does this mean for you as a developer?
If your application runs in ARM64 environments like AWS Graviton, you'll notice faster runtimes and more efficient resource use. Additionally, improvements in JIT (Just-In-Time compilation) ensure your code adapts better to these architectures.
Console.WriteLine($"Running on: {System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture}");
With this snippet, you can validate that your application is leveraging ARM64, ensuring you're maximizing performance on these platforms.
1.3. Application Initialization Improvements
The runtime now reduces startup times for .NET applications, crucial for microservices and containerized applications. Have you ever noticed applications taking a long time to start when part of an orchestrator like Kubernetes? In .NET 9, this issue is addressed with improvements that streamline initial loading.
Specific cases:
- Applications can now load with more optimized configurations.
- The time required to initialize assemblies has decreased significantly.
var app = WebApplication.CreateBuilder(args).Build();
app.MapGet("/", () => "Hello, .NET 9!");
app.Run();
When you deploy this minimal application in a Docker container, you'll notice a significant reduction in startup times compared to previous versions.
1.4. Just-In-Time (JIT) Compilation Updates
The JIT in .NET 9 is not only faster but also smarter. Now, certain optimizations previously only available in Ahead-Of-Time (AOT) compilation are available in JIT, benefiting applications with complex execution flows.
Developer advantages:
This means you can rely on your code being optimized at runtime without needing to change additional settings.
int Compute(int x, int y) => x * y + (x / y);
Console.WriteLine(Compute(10, 5));
In .NET 9, these types of complex arithmetic operations take advantage of compiler-level optimizations, running faster and using fewer resources.
1.5. Enhanced Performance Diagnostics
When working with tools like dotnet-counters
or dotnet-trace
, organizing and securing logs across environments can become a significant challenge. While these tools provide deep insights, managing logs effectively often requires additional effort. A practical way to simplify this is by using solutions like ByteHide Logs, which centralizes all application logs into a single, secure platform. This allows you to filter and analyze logs effortlessly, while ensuring their protection with end-to-end encryption, addressing compliance and privacy requirements seamlessly.
dotnet-counters monitor --process-id <PID>
Using these tools alongside runtime optimizations allows you to identify performance issues and solve them before they affect users.
2. .NET Libraries: More Tools and Flexibility
The libraries in .NET 9 have received a series of significant updates aimed at improving performance, security, and the developer experience. From new capabilities in JSON serialization to optimizations in LINQ and expanded support for modern cryptographic algorithms, these improvements are designed to make .NET development more powerful and efficient.
2.1. More Efficient JSON Serialization
JSON serialization has been a key focus in .NET 9, with System.Text.Json
receiving enhancements that make working with structured data easier and faster. You can now serialize and deserialize record types and immutable structures without complex configurations.
Practical Example:
public record Product(string Name, decimal Price);
var product = new Product("Laptop", 1500.75m);
string json = JsonSerializer.Serialize(product);
Console.WriteLine(json); // {"Name":"Laptop","Price":1500.75}
var deserialized = JsonSerializer.Deserialize<Product>(json);
Console.WriteLine(deserialized?.Name); // Laptop
Additionally, handling large collections has been improved, reducing processing time for data-intensive applications.
2.2. Goodbye to BinaryFormatter
With .NET 9, Microsoft has officially removed BinaryFormatter
. This decision, driven by security concerns, encourages developers to adopt modern alternatives like System.Text.Json
, XmlSerializer
, or specific solutions like Protobuf.
What does this mean for you?
The removal of BinaryFormatter
pushes developers toward modern serialization tools like System.Text.Json
, but this shift highlights the importance of managing secrets such as API keys or certificates securely. Many developers face the risk of exposing sensitive data in their codebases. Tools like ByteHide Secrets streamline this process by securely storing and dynamically managing secrets, ensuring they remain protected and up-to-date, even as application needs evolve.
2.3. System.Linq Optimizations
LINQ, one of the most beloved tools in .NET, has received significant optimizations in this version. The new TryGetNonEnumeratedCount
functionality allows you to get the size of a collection without fully enumerating it, saving time and resources in data-intensive scenarios.
Practical Example:
IEnumerable<int> numbers = Enumerable.Range(1, 1000);
if (numbers.TryGetNonEnumeratedCount(out int count))
{
Console.WriteLine($"Number of elements: {count}");
}
Moreover, common operations like Where
and Select
are now faster thanks to internal processing improvements.
2.4. Expanded Regex Support
In .NET 9, System.Text.RegularExpressions
now includes support for precompiled regular expressions, enabling significantly better performance in scenarios where patterns are reused.
Practical Example:
var regex = new Regex(@"\d{4}-\d{2}-\d{2}", RegexOptions.Compiled);
Console.WriteLine(regex.IsMatch("2023-11-19")); // True
This is especially useful for applications that process large volumes of text, such as validations and data analysis.
2.5. Logging with Source Generators
The logging system in .NET 9 has been optimized with the use of source generators, allowing log messages to be generated at compile time. This reduces runtime overhead and improves efficiency in applications that generate large amounts of logs.
[LoggerMessage(0, LogLevel.Information, "Application started at {StartTime}")]
public static partial void LogAppStart(this ILogger logger, DateTime StartTime);
This not only improves performance but also minimizes errors in manually creating log messages.
2.6. KMAC Algorithm, ChaCha20-Poly1305, and HashData
.NET 9 extends its support for modern cryptographic algorithms, introducing KMAC and ChaCha20-Poly1305. These algorithms offer fast and secure encryption, especially useful for mobile applications, IoT, and other environments where performance is critical.
Practical Example:
using var chacha20 = new ChaCha20Poly1305(key);
byte[] ciphertext = chacha20.Encrypt(nonce, plaintext, associatedData);
Moreover, the new HashData
method simplifies the creation of secure hashes:
byte[] hash = SHA256.HashData(Encoding.UTF8.GetBytes("secure data"));
Console.WriteLine(Convert.ToBase64String(hash));
Incorporating new cryptographic algorithms like KMAC and ChaCha20-Poly1305 enhances application security but requires reliable management of sensitive data. For this, ByteHide Storage offers an ideal solution, providing native integration with post-quantum cryptographic protocols such as Kyber and FrodoKEM. It ensures that sensitive data remains encrypted from end to end, even in cloud environments, addressing future-proofing concerns against emerging computational threats.
2.7. Support for ref struct
The .NET 9 libraries now allow working with ref struct
in more scenarios, opening up new possibilities for high-performance applications. This is particularly useful when handling sensitive data or large memory blocks.
2.8. Networking: HTTP/3 and More
.NET 9 enhances support for HTTP/3, enabling faster and more efficient connections. Additionally, sockets and System.Net.Http
tools have been optimized to improve performance in network-dependent applications.
If you work with microservices or modern APIs, these improvements will help you take advantage of the latest network protocols.
2.9. Reflection Optimizations
Reflection, a critical tool for frameworks like ORMs or dependency injection systems, is now more efficient in .NET 9. Operations such as retrieving types or methods through System.Reflection
execute faster, improving overall application performance.
Type type = typeof(MyClass);
var methods = type.GetMethods(BindingFlags.Public | BindingFlags.Instance);
These optimizations are crucial for high-traffic applications that rely heavily on Reflection.
3. .NET SDK: Smarter Tools
The .NET 9 SDK introduces features that enhance version management and security audits:
3.1 Workload Sets
With .NET 9 simplifying workload management and improving compilation processes, ensuring the security of compiled binaries becomes essential. ByteHide Shield provides advanced features such as tamper detection and runtime integrity checks, safeguarding your software against unauthorized modifications while maintaining optimal performance and functionality.
3.2 Security Audits in NuGet
NuGet's improved security audits are a great step forward, but effectively managing and securing dependencies still requires a proactive approach. Tools like ByteHide Radar enhance this process by combining Software Composition Analysis (SCA) with Static Application Security Testing (SAST). This dual approach enables the identification of vulnerabilities not just in third-party packages, but also in your code, providing actionable recommendations to mitigate risks early in the development cycle.
3.3 MSBuild Improvements
- Parallel test execution.
- New MSBuild script analyzers to detect configuration issues.
- Shield now fully supports .NET 9, integrating enhanced protection mechanisms directly into the MSBuild process. It ensures that application code is secured during compilation, safeguarding against reverse engineering and tampering, while maintaining seamless compatibility with modern .NET workflows.
4. Artificial Intelligence: A Broader Focus
.NET 9 positions itself as a robust platform for AI with new tensor types and libraries for manipulating data and machine learning models.
4.1 TensorPrimitives and Tensor
These new types simplify complex mathematical operations for machine learning models.
Example:
Tensor<float> tensor = new Tensor<float>(new[] { 1.0f, 2.0f, 3.0f });
TensorPrimitives.Add(tensor.Span, 2.0f);
4.2 ML.NET 4.0
- New capabilities for tokenizers.
- Improved ONNX model loading.
- Integration with TorchSharp for advanced models like Llama.
5. .NET Aspire 9.0: Innovations for Distributed Applications
.NET Aspire 9.0 brings a series of significant updates that optimize the development, orchestration, and management of distributed applications. Designed to make the most of .NET 8 (LTS) and .NET 9 (STS), this version introduces improvements focused on developer experience, interactivity, and integrations. Here, we break down the most important innovations.
5.1. Improved Developer Experience
New Installation via SDK
Unlike previous versions, .NET Aspire 9 simplifies the environment setup by removing the need to install workloads. You can now install the SDK directly in the app host project.
Example of updated template installation:
dotnet new install Aspire.ProjectTemplates::9.0.0
This makes the initial setup more agile and flexible for developers working on multiple Aspire projects.
5.2. Dashboard Improvements: Management and Interactivity
The .NET Aspire 9 dashboard introduces new features to facilitate the administration of distributed applications.
Resource Lifecycle Management
You can now stop, start, and restart individual resources directly from the dashboard without restarting the entire app host. This is useful for making quick changes to projects, containers, or executables.
Example: Reassign a debugger after restarting a project:
- Debugging resources reattach automatically when restarted.
Mobile Compatibility
The dashboard is now responsive, allowing applications to be managed from mobile devices with an optimized user experience.
Sensitive Properties and Volumes
You can now mark properties as sensitive, automatically masking them in the interface. Additionally, the visualization of configured volumes and health checks has been improved.
# Command to filter logs with masked sensitive properties
dotnet-aspire dashboard --filter sensitive
5.3. Optimized Telemetry
Telemetry is more flexible and powerful in this version, with features such as:
- Advanced Filters: You can now filter traces by specific attributes, like HTTP routes.
- Integration with OpenTelemetry from the browser: Web applications can send structured logs, traces, and metrics to the dashboard.
Example: Configuring OpenTelemetry in a SPA:
import { trace } from '@opentelemetry/api';
trace.getTracer('aspire-tracer').startSpan('Request initiated');
This ensures developers have a consolidated view of frontend and backend telemetry.
5.4. App Host and Orchestration
Wait for Dependencies
You can now define a resource to wait for another to be "ready" before starting. This is ideal for avoiding connection errors in containers.
var rabbit = builder.AddRabbitMQ("rabbit");
builder.AddProject<Projects.Api>("api")
.WithReference(rabbit)
.WaitFor(rabbit);
Configurable Health Checks
Configurable health checks have been added to determine when a resource is operational. These checks can be based on HTTP states or specific configurations.
builder.AddContainer("catalog-api")
.WithHttpHealthCheck("/health")
.WithLifetime(ContainerLifetime.Persistent);
This ensures dependent resources only start when they are fully functional.
5.5. Persistent Containers
You can now define persistent containers that are not deleted when the app host stops. This is useful for resources that need to remain operational regardless of the application's lifecycle.
Example: Create a persistent container for RabbitMQ:
var queue = builder.AddRabbitMQ("rabbit")
.WithLifetime(ContainerLifetime.Persistent);
5.6. Improved Integrations
Redis Insight
Redis integration now includes support for Redis Insight, offering a graphical interface to visualize and manage data in real-time.
builder.AddRedis("redis")
.WithRedisInsight();
Azure Functions (Preview)
.NET Aspire 9 introduces preliminary support for Azure Functions, allowing serverless functions to be integrated directly into the host.
Example: Configure an HTTP function in Azure Functions:
builder.AddAzureFunctionsProject<Projects.MyFunctionApp>("functionapp")
.WithExternalHttpEndpoints();
5.7. Customization of Azure Container Apps
APIs have been added to customize Azure Container Apps without modifying infrastructure files (Bicep).
For example, you can now scale an application to zero replicas programmatically:
builder.AddAzurePostgresFlexibleServer("pgsql")
.RunAsContainer()
.PublishAsAzureContainerApp((module, containerApp) =>
{
containerApp.Template.Value!.Scale.Value!.MinReplicas = 0;
});
6. ASP.NET Core 9.0: Essential Improvements for Modern Web Applications
ASP.NET Core 9.0 continues to strengthen its position as the ideal framework for building fast, efficient, and modern web applications. This version introduces significant optimizations in serving static files, new capabilities in Blazor and SignalR, and improvements in minimal APIs. Below, we explore these updates from a developer's perspective.
6.1. Static Asset Delivery Optimization
The new MapStaticAssets
function revolutionizes how ASP.NET Core applications serve static files. Now, production best practices like compression, caching, and ETag usage can be implemented without complex manual configurations.
What Makes MapStaticAssets Different?
- Advanced Compression: Support for gzip in development and gzip + Brotli in production.
- Content-Based ETags: Ensures browsers only download files if the content has changed.
-
Reduced Size: Example with MudBlazor:
- Original: 588.4 KB.
- Compressed: 46.7 KB (92% reduction).
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.MapStaticAssets();
app.MapRazorPages();
app.Run();
When to Use It?
Replace UseStaticFiles
in most cases, except when serving files from external locations, such as disks.
6.2. Blazor: More Integration and New Capabilities
Template for Blazor and .NET MAUI Hybrid Solutions
A new template simplifies creating native and web applications that share the same user interface. This approach fosters code reuse and supports multiple platforms like Android, iOS, Mac, Windows, and Web.
dotnet new maui-blazor-web
Improved Server-Side Reconnection
- Immediate reconnection when the browser returns to a sleeping tab.
- Configurable backoff strategies to customize retry intervals.
Blazor.start({
circuit: {
reconnectionOptions: {
retryIntervalMilliseconds: (previousAttempts) => previousAttempts * 1000,
},
},
});
6.3. SignalR: Enhanced Real-Time Communication
Support for Polymorphic Types in Hubs
SignalR now allows using base classes to enable polymorphic scenarios in Hub methods.
[JsonPolymorphic]
[JsonDerivedType(typeof(JsonPersonExtended))]
public class JsonPerson { public string Name { get; set; } }
public class MyHub : Hub
{
public void HandlePerson(JsonPerson person) => Console.WriteLine(person.Name);
}
Real-time communication frameworks like SignalR bring great interactivity but also introduce runtime vulnerabilities. Ensuring runtime security is critical, especially in distributed or IoT environments. With ByteHide Monitor, you can continuously protect your applications by dynamically detecting and neutralizing runtime threats, offering peace of mind in scenarios where secure environments cannot be guaranteed.
WebSocket Compression for Interactive Components
By default, SignalR enables compression for WebSocket, improving efficiency in real-time connections.
6.4. Minimal APIs: Simplification and Extensibility
New Methods in TypedResults
ASP.NET Core 9.0 introduces new methods in TypedResults
, like InternalServerError
, which facilitates error handling in minimal APIs.
app.MapGet("/", () => TypedResults.InternalServerError("Internal error"));
OpenAPI Compatibility
You can now generate OpenAPI documentation directly from your controllers or minimal APIs, with support for Native AOT.
builder.Services.AddOpenApi();
app.MapOpenApi();
6.5. Additional Improvements
- Integration with Bootstrap 5.3.3 and jQuery 3.7.1.
- Updated support for authentication and authorization with OpenID Connect.
- Advanced metrics in Kestrel: Includes detailed reasons for connection closures.
7. C# 13: The 11 Most Notable Language Updates
Based on the insightful session led by Mads Torgersen and Dustin Campbell at the .NET Conf 2024, we’ve compiled a concise summary of the most exciting new features and enhancements introduced in C# 13. This overview highlights the key advancements designed to improve developer productivity, streamline coding workflows, and expand the language's capabilities for modern applications. Stay tuned to explore what makes C# 13 a game-changer for the .NET ecosystem.
With the arrival of C# 13, developers have access to new tools and features designed to improve productivity, reduce repetitive code, and make the most out of .NET 9. Here is a complete breakdown of the 11 updates introduced in this version.
7.1. More Flexible String Interpolation
One of the most anticipated updates is the ability to nest interpolated expressions directly within a string. This eliminates the need for additional concatenations.
int x = 5, y = 10;
Console.WriteLine($"The sum of {x} and {y} is {x + y}");
Now you can build more complex strings without worrying about errors or lack of clarity.
7.2. Named Parameters in Attributes
C# 13 allows passing arguments to attributes using parameter names, which improves readability and reduces errors when working with metadata.
[ExampleAttribute(Required = true, Message = "This field is required")]
public string Field { get; set; }
This syntax is especially useful when working with attributes that have multiple optional parameters.
7.3. Improved ref fields
in Structs
The optimized handling of ref struct
in .NET 9 allows developers to enhance performance in memory-intensive applications. However, securing these performance-critical components is equally important. Solutions like ByteHide Shield protect your intellectual property by combining robust obfuscation techniques, control flow protection, and anti-debugging measures, making it nearly impossible for attackers to reverse-engineer or tamper with your software.
ref struct MyStruct
{
public ref int MyField;
public MyStruct(ref int value)
{
MyField = ref value;
}
}
This greatly benefits high-performance applications that manipulate sensitive or complex data.
7.4. List Initialization in Collection Expressions
C# 13 introduces a cleaner syntax for initializing lists and collections, eliminating the need for verbose initializers.
var numbers = [1, 2, 3, 4, 5];
This new syntax makes the code more intuitive, especially when working with large data structures.
7.5. Safe Access to Nullable Properties
The safe access operator now extends to object initializers, improving safety and readability in complex structures.
var person = new Person
{
Name = anotherObject?.Property ?? "Unknown"
};
This reduces the risk of runtime exceptions when working with potentially null data.
7.6. Improvements in readonly struct
It is now possible to declare extension methods on readonly struct
without losing the benefits of immutability.
public readonly struct Point
{
public int X { get; }
public int Y { get; }
public Point(int x, int y) => (X, Y) = (x, y);
public int CalculateDistance() => Math.Abs(X - Y);
}
This improvement simplifies working with immutable structs, making the code clearer and more efficient.
7.7. Improved Constant Handling
C# 13 allows defining constants that were previously not possible, such as DateTime
values.
public const DateTime StartDate = new DateTime(2024, 1, 1);
This makes it easier to use predefined constants in configurations and static data.
7.8. Changes in Pattern Matching
Improvements have been introduced that expand the capabilities of pattern matching
, including support for more complex logical patterns.
if (obj is int i and > 0)
{
Console.WriteLine($"Positive number: {i}");
}
These updates make the code more expressive and less error-prone.
7.9. Improved switch
with Type Expressions
You can now combine type expressions and patterns in more compact switch
statements.
string GetMessage(object obj) => obj switch
{
int i => $"It's a number: {i}",
string s => $"It's a string: {s}",
_ => "Unknown type"
};
This approach simplifies logic and improves code clarity.
7.10. New Capabilities in String Interpolation
It is now possible to use interpolated expressions in more contexts, such as property initializers.
var message = new { Text = $"Hello, {user.Name}" };
This makes handling dynamic strings even more natural.
7.11. Enhanced Generic Constraints
Finally, C# 13 introduces new capabilities in generic constraints, allowing for more flexible and robust method definitions.
public static void Process<T>(T element) where T : notnull
{
Console.WriteLine(element);
}
These improvements are essential for libraries that handle multiple data types safely.
8. What's New in F# 9
F# 9 adds features focused on security and productivity:
- Support for nullable reference types.
-
.Is*
properties for discriminated unions. - Partial active patterns can now return
bool
. - Preference for extension methods over intrinsic properties.
- Empty body expressions for computation expression builders.
- New randomization functions for collections.
- Improved compatibility with C# collections.
9. What's New in .NET MAUI for .NET 9: More Power and Flexibility for Cross-Platform Apps
Version 9 of .NET MAUI (Multi-platform App UI) focuses on improving product quality and expanding its capabilities. With new controls, performance improvements, and developer tools, this update sets a higher standard for cross-platform applications on Android, iOS, Mac Catalyst, and Windows.
9.1. Minimum Deployment Requirements
.NET MAUI 9 updates its deployment targets:
- iOS: Minimum required 12.2.
- Mac Catalyst: Minimum required 15.0 (macOS 12.0).
- Android and Windows: No changes from previous versions.
9.2. New Controls
HybridWebView
The HybridWebView control allows hosting HTML, CSS, and JavaScript content directly in a native .NET MAUI application. It also facilitates two-way communication between JavaScript code and C#.
Main Use:
- Ideal for integrating existing web applications like React or Angular within a MAUI app.
- Enables execution of local web content on the device.
<HybridWebView Source="index.html"
HostPage="wwwroot/index.html" />
TitleBar for Windows
You can now customize the title bar of your Windows application using the TitleBar control.
Example in XAML:
<Window.TitleBar>
<TitleBar Title="My Application"
Icon="icon.png"
HeightRequest="46">
<TitleBar.Content>
<SearchBar Placeholder="Search here"
HorizontalOptions="Fill"
VerticalOptions="Center" />
</TitleBar.Content>
</TitleBar>
</Window.TitleBar>
Key Features:
- Fully customizable: Add main content, start content, and end content.
- Supports dark and light themes.
- Upcoming support: Mac Catalyst in a future release.
9.3. Improvements to Existing Controls
BlazorWebView
- On iOS and Mac Catalyst, BlazorWebView content is now hosted by default on
localhost
, improving stability. - Introduction of fire-and-forget option for asynchronous disposal, reducing risks of deadlocks.
CollectionView and CarouselView
- New optional handlers have been added to improve performance and stability on iOS and Mac Catalyst.
builder.ConfigureMauiHandlers(handlers =>
{
handlers.AddHandler<CollectionView, CollectionViewHandler2>();
handlers.AddHandler<CarouselView, CarouselViewHandler2>();
});
Soft Keyboard
Expanded support for specific input types such as:
-
Password, Date, and Time in controls like
Entry
andEditor
.
<Entry Keyboard="Date" />
9.4. Compiled Bindings in Code and XAML
Compiled Bindings in Code
.NET MAUI 9 introduces compiled bindings that eliminate the need to use strings for property paths, reducing errors and improving performance.
MyLabel.SetBinding(Label.TextProperty, static (Entry entry) => entry.Text);
Advantages:
- Compile-time validation of bindings.
- Better debugging experience.
- Full support in NativeAOT.
9.5. Compilation with Native AOT and Full Trimming
Native AOT
.NET MAUI 9 enables Ahead of Time (AOT) compilation for iOS and Mac Catalyst. This results in applications that are:
- 2.5x smaller.
- 2x faster at startup.
Full Trimming
Removes unnecessary code from applications to reduce their size. Configurable in the project file:
<PropertyGroup>
<TrimMode>Full</TrimMode>
</PropertyGroup>
Limitations: Some features, like HybridWebView
, are not compatible with full trimming.
9.6. Project Templates and Practical Examples
New templates include:
- Todo List Apps: Based on SQLite with visualization thanks to the Syncfusion toolkit.
- Blazor Hybrid Templates: Combine native and web applications using Blazor.
dotnet new maui --sample-content -n MyProject
dotnet new maui-blazor-web -n MyBlazorProject
9.7. Native API and Multi-Window Support
Native API
.NET MAUI now includes complete APIs for native integration scenarios, simplifying the conversion of .NET MAUI views to their native equivalents.
var nativeView = mauiView.ToPlatform(mauiApp.Services);
Multi-Window Support
Ability to activate specific windows on Mac Catalyst and Windows:
Application.Current?.ActivateWindow(windowToActivate);
9.8. Compatibility and Deprecated APIs
Key Deprecations:
- The
Frame
control has been replaced byBorder
. - The
MainPage
property is now set inWindow.Page
for greater flexibility.
Extended Compatibility:
- Full support for iOS 18 and Mac Catalyst 15 with Xcode 16.
- Android API level 35.
10. WPF in .NET 9: Revamping Desktop UI Development
Windows Presentation Foundation (WPF) continues to evolve to offer modern and flexible tools for desktop application development. In .NET 9, WPF focuses on enhancing visual capabilities and introducing new features, such as support for Fluent themes and Windows accent colors. Here, we break down all the new updates.
10.1. Fluent Theme: Modern Style for Windows 11
The new Fluent theme introduces a more modern and consistent visual design aligned with Windows 11. This theme includes support for light and dark modes, as well as integration with the system accent color.
How to Apply It?
You can use the Fluent theme in two ways:
- Configuring the
ThemeMode
at the application or window level. - Referencing the Fluent theme resource dictionary in the XAML file:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/PresentationFramework.Fluent;component/Themes/Fluent.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
This integration ensures that WPF applications maintain a current design that meets user expectations.
10.2. ThemeMode
Property for Dynamic Style Configuration
The new ThemeMode
property makes it easier to configure the Fluent theme directly in the application or specific windows. You can define whether the app respects the system mode, stays fixed in light or dark mode, or uses the classic Aero2 theme.
Example: Configure Dark Mode at the Window Level:
<Window x:Class="MyApp.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Title="Main Window"
ThemeMode="Dark">
</Window>
This flexible approach simplifies app customization and ensures a consistent experience across devices.
10.3. Custom Accent Colors
WPF now allows leveraging the user's configured accent color in Windows, adding a personal touch to interfaces. It also offers light and dark versions of this color, ready to be used dynamically in your applications.
How to Use the Accent Color?
<TextBlock Text="Welcome"
Foreground="{DynamicResource {x:Static SystemColors.AccentColorBrushKey}}" />
With this configuration, any change in the system accent color will automatically reflect in the application without needing a restart.
10.4. Hyphen-Based Ligature Support
In response to community requests, WPF in .NET 9 adds support for hyphen-based ligatures within text controls like TextBlock
. This significantly improves the aesthetics of typography in applications that rely on advanced fonts.
In .NET 8:
In .NET 9 🔥
10.5. Removal of BinaryFormatter
As part of an ongoing effort to improve security, WPF completely removes BinaryFormatter
, which has been deemed unsafe due to deserialization vulnerabilities. Now, any attempt to use it will throw a PlatformNotSupportedException
.
What to Do If You Still Use BinaryFormatter?
You should migrate to modern alternatives, such as System.Text.Json
or XmlSerializer
, to handle data securely.
11. Windows Forms in .NET 9: New Capabilities for Modern Desktop Applications
Windows Forms remains a solid and reliable solution for desktop application development on Windows. With .NET 9, the platform introduces key improvements in functionality, compatibility, and design, integrating modern features that make desktop applications more efficient and visually appealing. Here are the most important updates.
11.1. Asynchronous Forms (Experimental)
Modern development requires compatibility with asynchronous communication models. In .NET 9, Windows Forms adds experimental support for asynchronous forms, including methods like Form.ShowAsync
, Form.ShowDialogAsync
, and Control.InvokeAsync
. This allows handling operations that require synchronization with the UI thread, such as WebView2 or libraries like Semantic Kernel.
Configuration to Use This Feature:
To enable these experimental APIs, add the following configuration to the project file:
<PropertyGroup>
<NoWarn>$(NoWarn);WFO5002</NoWarn>
</PropertyGroup>
This advancement is essential for applications that integrate multiple frameworks or require smooth communication between asynchronous components.
11.2. Goodbye to BinaryFormatter
Following best security practices, Windows Forms has removed the use of BinaryFormatter
, a class vulnerable to deserialization attacks. Now, attempting to use this functionality will throw a PlatformNotSupportedException
.
Windows Forms has internally replaced this dependency with a more secure subset for specific scenarios, such as clipboard operations and the form designer.
What Does This Mean?
If you still rely on BinaryFormatter
, it is crucial to migrate to modern alternatives like System.Text.Json
or XmlSerializer
.
11.3. Experimental Support for Dark Mode
.NET 9 introduces preliminary support for dark mode in Windows Forms, with plans for completion in .NET 10. You can now set the system color mode with a simple line of code:
Application.SetColorMode(SystemColorMode.Dark);
Dark mode is ideal for applications that need to follow system preferences or provide a more comfortable experience in low-light environments.
Available Modes:
-
SystemColorMode.Classic
: Light mode, as in previous versions. -
SystemColorMode.System
: Follows Windows settings. -
SystemColorMode.Dark
: Activates dark mode directly.
11.4. Improvements in FolderBrowserDialog
One of the most requested improvements is the ability to select multiple folders in FolderBrowserDialog
. This is now possible by setting the Multiselect
property to true
.
var dialog = new FolderBrowserDialog
{
Multiselect = true
};
if (dialog.ShowDialog() == DialogResult.OK)
{
foreach (var path in dialog.SelectedPaths)
{
Console.WriteLine($"Selected folder: {path}");
}
}
This simplifies tasks such as bulk operations across multiple directories.
11.5. New Capabilities in System.Drawing
The System.Drawing
library has received several improvements, including:
Image Effects with GDI+
You can now apply advanced visual effects, such as blurs, contrast adjustments, and tints, directly to bitmaps.
var bitmap = new Bitmap("image.jpg");
var effect = new System.Drawing.Imaging.Effects.BlurEffect();
bitmap.ApplyEffect(effect, Rectangle.Empty);
These capabilities allow adding high-quality graphics to your applications without the need for external tools.
Span Compatibility
Many methods that previously only accepted arrays now support ReadOnlySpan
, optimizing memory handling and improving performance.
Graphics.DrawLines(Pens.Black, new ReadOnlySpan<Point>(points));
11.6. Improvements in ToolStrip
The ToolStrip
control now includes new properties and events that enhance its functionality:
-
AllowClickThrough
: Allows interaction with the control even when the window is not focused. -
SelectedChanged
: Event that detects when a menu item is highlighted, replacing the functionality of the deprecatedMenuItem.Select
.
var toolStripItem = new ToolStripMenuItem("File");
toolStripItem.SelectedChanged += (sender, args) => Console.WriteLine("Item selected");
These improvements allow building more dynamic and functional menus.
As we move forward into a new era of software development, .NET 9 emerges as a powerful platform that empowers developers to build more secure, efficient, and innovative applications. With advancements spanning across various areas, from modernizing desktop applications with Windows Forms and WPF to enhancing cross-platform capabilities with .NET MAUI, .NET 9 caters to a wide range of development needs.
The inclusion of updates in C#, F#, and the integration of new performance and security features ensures that .NET developers are equipped with state-of-the-art tools to stay ahead in an ever-evolving tech landscape. Whether you're developing for the web, mobile, or desktop, .NET 9 has something valuable to offer.
Take the opportunity to explore these new features, experiment with the latest improvements, and continue building the future of software with .NET 9. The journey of innovation has just begun, and the tools are now in your hands.
Top comments (0)