DEV Community

Cover image for What’s New in .NET 10: Everything You Need to Know
ByteHide
ByteHide

Posted on • Originally published at bytehide.com

What’s New in .NET 10: Everything You Need to Know

If you’re a .NET developer, get ready .NET 10 is here and it’s a Long Term Support (LTS) release! That means three years of updates, optimizations, and stability, making it a solid choice for production environments. Whether you’re working on high-performance web apps, cross-platform mobile solutions, or enterprise software, this version brings tons of improvements across the entire .NET ecosystem.

In this article, we’ll dive deep into everything that’s new in .NET 10, from runtime performance boosts to SDK changes, ASP.NET Core updates, EF Core enhancements, and much more. We’ve broken it all down so you can quickly understand what’s changed, what’s improved, and how it impacts your code.

So, grab your keyboard, fire up your IDE, and let’s explore what’s new in .NET 10! 🔥

To create this article, I gathered information directly from the official Microsoft documentation, the official .NET repository on GitHub, and the .NET 10 announcement video.

Image description

Additionally, I referenced insights and analyses from key experts in the .NET community, including:

An LTS release with extended support

.NET 10 is the successor to .NET 9 and will be a Long-Term Support (LTS) version, meaning it will receive updates and maintenance for 3 years.

If you want to try this version, you can download it here: Download .NET 10.

Additionally, Microsoft has set up a GitHub Discussions section where developers can provide feedback and report issues: GitHub Discussions.

.NET 10 Runtime Improvements

The .NET 10 runtime has been optimized with new features focused on improving performance and reducing abstraction overhead in the code. Below, we explore the three main enhancements introduced in this version.

Array Interface Method Devirtualization

One of .NET 10’s key goals is to reduce abstraction overhead in commonly used language features. To achieve this, the JIT (Just-In-Time Compiler) can now devirtualize array interface methods, enabling more aggressive optimizations.

Before .NET 10, looping through an array using a simple for loop was easy for the JIT to optimize by removing bounds checks and applying loop optimizations introduced in .NET 9:

static int Sum(int[] array)
{
    int sum = 0;
    for (int i = 0; i < array.Length; i++)
    {
        sum += array[i];
    }
    return sum;
}
Enter fullscreen mode Exit fullscreen mode

However, using a foreach loop with an interface like IEnumerable<int> introduced virtual calls, preventing optimizations such as inlining and bounds check elimination:

static int Sum(int[] array)
{
    int sum = 0;
    IEnumerable<int> temp = array;

    foreach (var num in temp)
    {
        sum += num;
    }
    return sum;
}
Enter fullscreen mode Exit fullscreen mode

Starting in .NET 10, the JIT can now detect and devirtualize these calls, optimizing the performance of foreach loops when iterating over arrays. This is just the first step in Microsoft’s broader plan to achieve performance parity between different abstraction implementations in .NET.

Stack Allocation of Value Type Arrays

In .NET 9, the JIT introduced the ability to allocate objects on the stack (stack allocation) when it could guarantee they would not outlive their parent method. This optimization reduces the load on the Garbage Collector (GC) and enables further performance improvements.

Now, in .NET 10, this capability has been extended to allow stack allocation of small, fixed-size arrays of value types that do not contain GC references.

Example

static void Sum()
{
    int[] numbers = { 1, 2, 3 };
    int sum = 0;

    for (int i = 0; i < numbers.Length; i++)
    {
        sum += numbers[i];
    }

    Console.WriteLine(sum);
}
Enter fullscreen mode Exit fullscreen mode

In this case, the JIT recognizes that numbers is a fixed-size array of three integers and does not outlive the Sum method, so instead of allocating it on the heap, it places it on the stack, improving memory efficiency.

This change helps reduce the abstraction penalty of reference types, further closing the performance gap between .NET and lower-level languages.

AVX10.2 Support

.NET 10 introduces support for Advanced Vector Extensions (AVX) 10.2 on x64-based processors. AVX is an instruction set designed to improve the speed of vector operations and parallel processing.

What does this mean for developers?

The new intrinsics available in the System.Runtime.Intrinsics.X86.Avx10v2 class will, in the future, allow performance improvements in mathematical calculations, graphics, artificial intelligence, and any application leveraging SIMD (Single Instruction, Multiple Data) processing.

📢 Important: Currently, no hardware supports AVX10.2, so JIT support for these instructions is disabled by default until compatible hardware becomes available.

Improvements in .NET 10 Libraries

The .NET 10 libraries have received significant performance improvements and new APIs that enhance data handling, optimize memory usage, and improve serialization efficiency. Below, we review the most notable updates.

Image description

Find Certificates by Thumbprint Beyond SHA-1

Finding certificates by thumbprint is a common operation, but until now, the X509Certificate2Collection.Find(X509FindType, Object, Boolean) method only supported searches using SHA-1.

.NET 10 introduces a new method that allows specifying the hash algorithm to use, increasing security and flexibility when searching for certificates.

Example

X509Certificate2Collection coll = store.Certificates.FindByThumbprint(HashAlgorithmName.SHA256, thumbprint);
Debug.Assert(coll.Count < 2, "Collection has too many matches, has SHA-2 been broken?");
return coll.SingleOrDefault();
Enter fullscreen mode Exit fullscreen mode

This enhancement enables secure searches for certificates using modern hash algorithms like SHA-256 or SHA-3-256, avoiding potential risks associated with similar hash lengths.

Support for PEM-Encoded Data in ASCII/UTF-8

The PEM (Privacy Enhanced Mail) format is widely used for storing certificates and keys as text. Previously, the PemEncoding class only worked with string (string) or ReadOnlySpan<char>, requiring manual conversion for ASCII-encoded files.

.NET 10 introduces a new method that allows reading PEM-encoded data directly from ASCII/UTF-8 files, eliminating unnecessary conversions and improving efficiency.

Example

Before .NET 10, data conversion was required before processing:

byte[] fileContents = File.ReadAllBytes(path);
char[] text = Encoding.ASCII.GetString(fileContents);
PemFields pemFields = PemEncoding.Find(text);
Enter fullscreen mode Exit fullscreen mode

Now, files can be read directly without conversion:

byte[] fileContents = File.ReadAllBytes(path);
PemFields pemFields = PemEncoding.FindUtf8(fileContents);
Enter fullscreen mode Exit fullscreen mode

This reduces memory consumption and improves performance when working with PEM files.

New ISOWeek Overloads for DateOnly

The ISOWeek class was originally designed to work with DateTime, but with the introduction of DateOnly, additional support was needed.

.NET 10 includes new ISOWeek overloads to work directly with DateOnly, simplifying week-based calculations without requiring conversions to DateTime.

New Methods

public static class ISOWeek
{
    public static int GetWeekOfYear(DateOnly date);
    public static int GetYear(DateOnly date);
    public static DateOnly ToDateOnly(int year, int week, DayOfWeek dayOfWeek);
}
Enter fullscreen mode Exit fullscreen mode

This improves precision and usability for applications that handle date calculations without time components.

ZipArchive Performance and Memory Improvements

The performance of ZipArchive has been enhanced in two key areas:

1️⃣ Optimized update mode: Previously, editing files inside a ZIP required loading all entries into memory, leading to high resource consumption. Now, file updates are more efficient, reducing RAM usage.

2️⃣ Parallelized extraction: Decompression is now faster, as data is processed in parallel, and internal data structures have been optimized to lower memory consumption.

These enhancements make ZipArchive more efficient when handling large file compression and extraction tasks.


New Overloads for OrderedDictionary

The OrderedDictionary<TKey, TValue> type has been improved with new overloads for TryAdd and TryGetValue, which now return the index of the entry, making data access more efficient.

New Overloads

public class OrderedDictionary<TKey, TValue>
{
    public bool TryAdd(TKey key, TValue value, out int index);
    public bool TryGetValue(TKey key, out TValue value, out int index);
}
Enter fullscreen mode Exit fullscreen mode

This allows developers to use the returned index for faster access and modifications.

Example Usage

if (!orderedDictionary.TryAdd(key, 1, out int index))
{
    int value = orderedDictionary.GetAt(index).Value;
    orderedDictionary.SetAt(index, value + 1);
}
Enter fullscreen mode Exit fullscreen mode

This improvement has already been applied to JsonObject, resulting in a 10-20% performance boost in property updates.

Support for ReferenceHandler in JsonSourceGenerationOptions

When using source generators for JSON serialization, circular references previously caused errors by default. In .NET 10, it is now possible to configure serialization behavior using ReferenceHandler.

Example

[JsonSourceGenerationOptions(ReferenceHandler = JsonKnownReferenceHandler.Preserve)]
[JsonSerializable(typeof(SelfReference))]
internal partial class ContextWithPreserveReference : JsonSerializerContext
{
}

internal class SelfReference
{
    public SelfReference Me { get; set; } = null!;
}
Enter fullscreen mode Exit fullscreen mode

This allows better control over reference handling in JSON serialization, preventing errors and improving compatibility with complex data structures.


Changes in the .NET 10 SDK

The .NET 10 SDK introduces significant improvements in dependency management, optimizing the build process and reducing disk space usage. One of the key updates is the removal of unnecessary framework-provided package references, which helps enhance performance and security in projects.

Pruning of Framework-Provided Package References

Starting in .NET 10, the NuGet Audit feature can now automatically remove unused framework-provided package references from your project.

How does this improvement impact development?

Faster build times: Fewer packages need to be restored and analyzed during builds.

Reduced disk space usage: Unnecessary dependencies are removed, optimizing project size.

Fewer false positives in security audits: Tools like NuGet Audit and other dependency scanners will produce fewer incorrect alerts.

When this feature is enabled, the application’s generated .deps.json file will contain fewer package references, as those already provided by the .NET runtime are automatically excluded.


Is this feature enabled by default?

Yes, this functionality is enabled by default for the following target frameworks (TFMs):

  • .NET 8.0 and .NET 10.0
  • .NET Standard 2.0 and later

How to disable it if needed?

If your project requires keeping all framework-provided package references, you can disable this feature by adding the following property to your .csproj or Directory.Build.props file:

<PropertyGroup>
    <RestoreEnablePackagePruning>false</RestoreEnablePackagePruning>
</PropertyGroup>
Enter fullscreen mode Exit fullscreen mode

This ensures that all package references remain included in the .deps.json file.


What’s New in .NET Aspire 9.1

.NET Aspire 9.1 introduces several improvements focused on user experience, dashboard customization, and local development optimizations. This version supports both .NET 8 (LTS) and .NET 9 (STS), allowing developers to take advantage of the latest features on either platform.

The main goal of this release was “polish, polish, polish”, addressing community feedback and enhancing overall quality-of-life improvements across the platform.


Upgrading to .NET Aspire 9.1

Upgrading to the new version is straightforward:

1️⃣ Update the SDK in your app host project file (MyApp.AppHost.csproj):

<Project Sdk="Microsoft.NET.Sdk">
    <Sdk Name="Aspire.AppHost.Sdk" Version="9.1.0" />
</Project>
Enter fullscreen mode Exit fullscreen mode

2️⃣ Check for NuGet package updates using Visual Studio’s NuGet Package Manager or via the command line in VS Code.

3️⃣ Update .NET Aspire templates by running the following command:

dotnet new update
Enter fullscreen mode Exit fullscreen mode

If your app host project file doesn’t reference Aspire.AppHost.Sdk, you might still be using .NET Aspire 8. In that case, refer to the upgrade documentation for .NET Aspire 9.


Improved Onboarding Experience

.NET Aspire 9.1 makes it easier to get started by introducing:

  • GitHub Codespaces template that pre-installs all necessary dependencies, templates, and the ASP.NET Core developer certificate.
  • Support for Dev Containers in Visual Studio Code, improving portability and consistency across development environments.

For more details, see:

🔗 Using .NET Aspire with GitHub Codespaces

🔗 Setting up Dev Containers in .NET Aspire


Dashboard UX & Customization

Every .NET Aspire release enhances the dashboard, and 9.1 is no exception. Key improvements include:

Resource Relationships

  • The dashboard now supports parent-child relationships for resources.
  • Example: When creating a Postgres instance with multiple databases, they are now nested under the same instance in the Resources page.

Localization Overrides

  • Users can now manually set the dashboard language, independent of the browser’s language settings.

Clear Logs & Telemetry

  • New buttons added to Console Logs, Structured Logs, Traces, and Metrics pages allow clearing data.
  • A “Remove all” button has been added in Settings to reset everything at once.

Resource Filtering

  • Users can now filter resources by type, state, and health for better visibility.

More Resource Details

When selecting a resource, the details pane now shows:

  • References & Back References
  • Volumes with mount types
  • Additional metadata for better insights

For more details, check out the 🔗 .NET Aspire Dashboard Resources page.


CORS Support for Custom Local Domains

Developers can now set the DOTNET_DASHBOARD_CORS_ALLOWED_ORIGINS environment variable to allow telemetry from custom browser apps (e.g., running on custom localhost domains).

For more details, visit:

🔗 Configuring the .NET Aspire dashboard


Console Log Enhancements

New Options:

  • Download logs to analyze them with external diagnostic tools.
  • Toggle timestamps on/off for a cleaner view.

For more details, check out:

🔗 Console Logs in .NET Aspire Dashboard


Local Development Enhancements

.NET Aspire 9.1 introduces multiple improvements to streamline local development:

Start Resources on Demand

  • Resources don’t need to start automatically with the app.
  • Developers can now mark resources with WithExplicitStart, allowing them to be started manually via the dashboard.

For more details:

🔗 Configuring Explicit Resource Start


Improved Docker Integration

  • .PublishAsDockerfile() now works across all projects and executable resources, enabling better customization of containers.

Cleaning Up Docker Networks

  • Fixed an issue where Docker networks were not removed after stopping an Aspire app.
  • Now, networks are properly cleaned up, ensuring a more efficient development environment.

Bug Fixes & Stability Improvements

.NET Aspire 9.1 resolves multiple reported issues, including:

Fixed "Address Already in Use" Errors

  • Address management has been improved to prevent conflicts during restarts.

Better Integration Handling

  • Various updates to Azure Service Bus, Event Hubs, and Cosmos DB improve compatibility and ease of use.

Service Bus & Event Hubs Enhancements

  • Developers can now define Service Bus queues, topics, and Event Hubs directly in the app host code.

🔗 Azure Service Bus Integration

🔗 Azure Event Hubs Integration


ASP.NET Core 10

ASP.NET Core 10 introduces several improvements across Blazor, SignalR, Minimal APIs, and OpenAPI 3.1. This update focuses on performance, ease of development, and better integration with modern web standards.


Blazor Enhancements

QuickGrid RowClass Parameter

Blazor’s QuickGrid component now includes a RowClass parameter, allowing developers to dynamically apply CSS classes to grid rows based on row data.

Example

<QuickGrid ... RowClass="ApplyRowStyle">
    ...
</QuickGrid>

@code {
    private string ApplyRowStyle({TYPE} rowItem) =>
        rowItem.{PROPERTY} == {VALUE} ? "{CSS STYLE CLASS}" : null;
}
Enter fullscreen mode Exit fullscreen mode

This provides more flexibility in styling grids based on specific conditions.


Blazor Script Optimization

Previously, Blazor scripts were served as embedded resources in the ASP.NET Core shared framework. In .NET 10, these scripts are now delivered as static web resources with automatic compression and fingerprinting, improving load times and caching efficiency.


Route Template Highlighting

The [Route] attribute now supports syntax highlighting for route templates, making it easier to visualize and manage endpoint structures in the code editor.


SignalR Enhancements

ASP.NET Core 10 brings updates to SignalR, though specific details will be provided in future previews.


Minimal APIs Enhancements

Minimal APIs continue to evolve, making it easier to build lightweight web services with fewer dependencies. Additional updates will be documented as they are released.


OpenAPI 3.1 Support

ASP.NET Core 10 introduces support for OpenAPI 3.1, which aligns with the 2020-12 JSON Schema Draft. This update makes API documentation more accurate and better structured but also introduces some breaking changes.

Key Changes in OpenAPI 3.1

  • Nullable properties no longer use nullable: true. Instead, they now use a type keyword with an array that includes null.
  • OpenAPI 3.1 is now the default version for generated documents, though developers can still configure OpenAPI 3.0 if needed.

Example: Setting OpenAPI Version

builder.Services.AddOpenApi(options =>
{
    options.OpenApiVersion = Microsoft.OpenApi.OpenApiSpecVersion.OpenApi3_0;
});
Enter fullscreen mode Exit fullscreen mode

For build-time OpenAPI document generation, the version can be specified using MSBuild options:

<OpenApiGenerateDocumentsOptions>--openapi-version OpenApi3_0</OpenApiGenerateDocumentsOptions>
Enter fullscreen mode Exit fullscreen mode

Breaking Changes in OpenAPI 3.1

One of the major changes in .NET 10 is the removal of OpenApiAny, which is now replaced by JsonNode.

Before (.NET 9 Example)

options.AddSchemaTransformer((schema, context, cancellationToken) =>
{
    if (context.JsonTypeInfo.Type == typeof(WeatherForecast))
    {
        schema.Example = new OpenApiObject
        {
            ["date"] = new OpenApiString(DateTime.Now.AddDays(1).ToString("yyyy-MM-dd")),
            ["temperatureC"] = new OpenApiInteger(0),
            ["temperatureF"] = new OpenApiInteger(32),
            ["summary"] = new OpenApiString("Bracing"),
        };
    }
    return Task.CompletedTask;
});
Enter fullscreen mode Exit fullscreen mode

After (.NET 10 Update)

options.AddSchemaTransformer((schema, context, cancellationToken) =>
{
    if (context.JsonTypeInfo.Type == typeof(WeatherForecast))
    {
        schema.Example = new JsonObject
        {
            ["date"] = DateTime.Now.AddDays(1).ToString("yyyy-MM-dd"),
            ["temperatureC"] = 0,
            ["temperatureF"] = 32,
            ["summary"] = "Bracing",
        };
    }
    return Task.CompletedTask;
});
Enter fullscreen mode Exit fullscreen mode

These changes affect all OpenAPI versions, even if OpenAPI 3.0 is explicitly specified.


Serving OpenAPI in YAML Format

ASP.NET Core 10 now allows serving the generated OpenAPI document in YAML format, which can be easier to read and maintain compared to JSON.

How to Enable YAML Format

app.MapOpenApi("/openapi/{documentName}.yaml");
Enter fullscreen mode Exit fullscreen mode

At the moment, YAML support is only available when serving OpenAPI documents via an endpoint. Build-time YAML generation is expected in a future release.


Response Descriptions in ProducesResponseType

The [ProducesResponseType] attribute now supports an optional description parameter, making API documentation clearer and more informative.

Example

[HttpGet(Name = "GetWeatherForecast")]
[ProducesResponseType<IEnumerable<WeatherForecast>>(StatusCodes.Status200OK, 
    Description = "The weather forecast for the next 5 days.")]
public IEnumerable<WeatherForecast> Get()
Enter fullscreen mode Exit fullscreen mode

This change improves OpenAPI documentation by providing a more detailed response description.


Authentication & Authorization Enhancements

Additional improvements in authentication and authorization will be detailed in future updates of ASP.NET Core 10.


Miscellaneous Improvements

Better Support for Testing Apps with Top-Level Statements

Previously, top-level statement apps in C# 9+ required developers to manually declare:

public partial class Program
Enter fullscreen mode Exit fullscreen mode

This was necessary so test projects could reference the Program class.

In .NET 10, a source generator automatically generates public partial class Program if it isn’t explicitly declared. If a developer manually adds it, a new analyzer will suggest removing it to avoid redundancy.


.NET MAUI for .NET 10

.NET MAUI in .NET 10 focuses on quality improvements across .NET MAUI, .NET for Android, .NET for iOS, and macOS. This update enhances stability, performance, and developer experience, ensuring a more polished and reliable multi-platform development framework.


Control Enhancements

CollectionView and CarouselView

  • In .NET 9, optional handlers were introduced for CollectionView and CarouselView on iOS and Mac Catalyst, improving performance and stability.
  • In .NET 10, these handlers are now the default, ensuring better responsiveness and reliability.

.NET for Android Improvements

Support for API 36 (Android 16) and JDK 21

  • .NET for Android now includes support for Android API 36 (Android 16 “Baklava”) and JDK 21, keeping the framework aligned with the latest Android developments.

To target the Android 16 preview API:

1️⃣ Download the Android 16 (Baklava) SDK via the Android SDK Manager.

2️⃣ Update your project’s TargetFramework to net10.0-android36.


Recommended Minimum Supported API Level

  • The default minimum supported Android API has been updated from 21 (Lollipop) to 24 (Nougat).
  • API 21 is still supported, but updating to API 24 is recommended to avoid runtime issues caused by Java default interface methods.

dotnet run Support for Android

Previously, the dotnet run command wasn’t supported for .NET for Android projects due to missing parameters for specifying the target device or emulator.

In .NET 10, Android projects can now be run using dotnet run, with new options:

// Run on a connected physical Android device
dotnet run -p:AdbTarget=-d  

// Run on a running Android emulator  
dotnet run -p:AdbTarget=-e  

// Run on a specific Android device or emulator  
dotnet run -p:AdbTarget="-s emulator-5554"
Enter fullscreen mode Exit fullscreen mode

The AdbTarget property allows developers to specify which device to use when running the application.


Marshal Methods Enabled by Default

A new marshal method mechanism was introduced in .NET 9, improving startup performance by optimizing how Java calls into C# code.

  • In .NET 9, this feature was disabled by default.
  • In .NET 10, it is enabled by default to further improve performance.

If startup hangs occur, it can be disabled using the following MSBuild property:

<PropertyGroup>
    <AndroidEnableMarshalMethods>false</AndroidEnableMarshalMethods>
</PropertyGroup>
Enter fullscreen mode Exit fullscreen mode

Improved Maven Library Binding

Developers using @(AndroidMavenLibrary) to download and bind Java libraries from Maven repositories can now specify an alternative artifact filename.

Example:

<ItemGroup>
    <AndroidMavenLibrary Include="com.facebook.react:react-android"
                         Version="0.76.0"
                         ArtifactFilename="react-android-0.76.0-release.aar" />
</ItemGroup>
Enter fullscreen mode Exit fullscreen mode

This improves flexibility when dealing with libraries that don’t follow a standard naming convention.


Faster Design-Time Builds

To speed up Visual Studio design-time builds, .NET 10 no longer invokes aapt2. Instead, .aar files and Android resources are parsed directly, reducing build times from over 2 seconds to under 600ms in some cases.


General Android Improvements

  • .NET for Android can now build with JDK 21.
  • Startup performance has been improved by removing paths that rely on System.Reflection.Emit.
  • Fixes for ApplicationAttribute.ManageSpaceActivity to prevent InvalidCastException errors.

.NET for iOS, tvOS, Mac Catalyst, and macOS

Updated Platform Support

.NET 10 now supports the latest platform versions:

  • iOS: 18.2
  • tvOS: 18.2
  • Mac Catalyst: 18.2
  • macOS: 15.2

Trimmer Warnings Enabled by Default

Previously, trimmer warnings were suppressed due to issues in the base class library. Now that these warnings have been resolved in .NET 9, they are enabled by default in .NET 10.

To disable trimmer warnings, add the following MSBuild property:

<PropertyGroup>
    <SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
</PropertyGroup>
Enter fullscreen mode Exit fullscreen mode

Bundling Original Resources in Libraries

Library projects in .NET MAUI can contain bundled resources like:

  • Storyboards
  • XIBs
  • Images
  • CoreML models
  • Texture atlases

Previous Issues

Previously, these resources were pre-processed before embedding, but this approach had some drawbacks:

Processing required a Mac and Apple’s toolchain.

Decision-making based on the original resources wasn’t possible during app builds.


.NET 9 & .NET 10 Changes

  • In .NET 9, opt-in support for embedding original resources in libraries was introduced.
  • In .NET 10, this behavior is enabled by default.

How to Opt Out

If you want to disable this behavior, use the following property:

<PropertyGroup>
    <BundleOriginalResources>false</BundleOriginalResources>
</PropertyGroup>
Enter fullscreen mode Exit fullscreen mode

This change simplifies library builds and gives developers more control over how resources are handled.


What’s New in EF Core 10

EF Core 10 (EF10) introduces improvements in LINQ query translation and enhancements to ExecuteUpdateAsync, making database operations more flexible and efficient.

Compatibility

  • EF Core 10 requires .NET 10 to compile and run.
  • It is not compatible with older .NET versions or .NET Framework.

LINQ and SQL Query Translation Improvements

EF Core 10 continues to refine query translation, optimizing performance and expanding support for commonly used LINQ operations.

Key Improvements

Translation support for DateOnly.ToDateTime(TimeOnly) #35194.

Optimized handling of consecutive LIMIT operations #35384.

Performance improvements for Count operations on ICollection<T> #35381.

These enhancements help ensure that queries are translated into efficient SQL while maintaining expected behavior.


Enhancements to ExecuteUpdateAsync

Easier Dynamic Updates

ExecuteUpdateAsync allows for arbitrary update operations in the database. Previously, these updates had to be specified using expression trees, making them difficult to construct dynamically.


Before (EF Core 9 – Using Expression Trees)

Updating a blog’s view count while conditionally modifying its name required manually constructing an expression tree, making the process complex and error-prone:

// Base setters - update the Views only
Expression<Func<SetPropertyCalls<Blog>, SetPropertyCalls<Blog>>> setters =
    s => s.SetProperty(b => b.Views, 8);

// Conditionally add SetProperty(b => b.Name, "foo") to setters, based on the value of nameChanged
if (nameChanged)
{
    var blogParameter = Expression.Parameter(typeof(Blog), "b");

    setters = Expression.Lambda<Func<SetPropertyCalls<Blog>, SetPropertyCalls<Blog>>>(
        Expression.Call(
            instance: setters.Body,
            methodName: nameof(SetPropertyCalls<Blog>.SetProperty),
            typeArguments: [typeof(string)],
            arguments:
            [
                Expression.Lambda<Func<Blog, string>>(Expression.Property(blogParameter, nameof(Blog.Name)), blogParameter),
                Expression.Constant("foo")
            ]),
        setters.Parameters);
}

await context.Blogs.ExecuteUpdateAsync(setters);
Enter fullscreen mode Exit fullscreen mode

After (EF Core 10 – Using Standard Lambdas)

In EF Core 10, ExecuteUpdateAsync now supports regular lambda expressions, making it much simpler to perform conditional updates dynamically:

await context.Blogs.ExecuteUpdateAsync(s =>
{
    s.SetProperty(b => b.Views, 8);
    if (nameChanged)
    {
        s.SetProperty(b => b.Name, "foo");
    }
});
Enter fullscreen mode Exit fullscreen mode

This improvement eliminates the need for complex expression tree manipulation, making updates easier to write and maintain.


What’s New in C# 14

C# 14 introduces several new language features, focusing on:

Improving code clarity

Reducing boilerplate

Enhancing performance

Key updates include:

  • The nameof operator for unbound generic types
  • Implicit conversions for Span<T>
  • New options for lambda parameters

These features require .NET 10 and are supported in Visual Studio 2022.


New field Keyword

The field keyword simplifies property accessors by eliminating the need for an explicitly declared backing field.

Before (C# 13 – Using Explicit Backing Field)

Previously, ensuring a property couldn’t be set to null required manually defining a backing field:

private string _msg;
public string Message
{
    get => _msg;
    set => _msg = value ?? throw new ArgumentNullException(nameof(value));
}
Enter fullscreen mode Exit fullscreen mode

After (C# 14 – Using field)

With the new field keyword, the compiler automatically generates the backing field:

public string Message
{
    get;
    set => field = value ?? throw new ArgumentNullException(nameof(value));
}
Enter fullscreen mode Exit fullscreen mode

This feature reduces boilerplate code while maintaining functionality. However, if a class already contains a member named field, developers can use @field or this.field to avoid conflicts.


Implicit Conversions for Span<T> and ReadOnlySpan<T>

C# 14 provides first-class support for Span<T> and ReadOnlySpan<T>, enabling more natural conversions between these types and standard arrays.

Key Benefits

Better performance without compromising safety.

More intuitive handling of spans, reducing the need for manual conversions.

Improved compatibility with extension methods and generic type inference.

These changes make working with spans more seamless, particularly in high-performance applications.


Unbound Generic Types in nameof

In previous versions of C#, the nameof operator could only be used with closed generic types (e.g., nameof(List<int>) would return "List").

New in C# 14

Now, unbound generic types can also be used:

Console.WriteLine(nameof(List<>)); // Outputs: "List"
Enter fullscreen mode Exit fullscreen mode

This feature improves metaprogramming scenarios where working with generic type names is necessary.


Modifiers for Simple Lambda Parameters

C# 14 allows adding parameter modifiers (scoped, ref, in, out, ref readonly) to lambda expressions without requiring explicit type declarations.

Before (C# 13 – Explicit Types Required for Modifiers)

TryParse<int> parse = (string text, out int result) => int.TryParse(text, out result);
Enter fullscreen mode Exit fullscreen mode

After (C# 14 – Type Inference Supported)

delegate bool TryParse<T>(string text, out T result);

TryParse<int> parse = (text, out result) => int.TryParse(text, out result);
Enter fullscreen mode Exit fullscreen mode

This change reduces redundancy and improves the readability of lambda expressions.


What’s New in Windows Forms for .NET 10

Windows Forms in .NET 10 introduces changes to clipboard serialization and deserialization, aligning with the broader effort to phase out BinaryFormatter. Additionally, new APIs have been introduced to facilitate JSON-based clipboard operations, providing a more secure and modern approach to data exchange.


Clipboard Serialization and Deserialization Changes

In .NET 9, BinaryFormatter was deprecated, affecting certain clipboard operations that relied on it. To ease the transition, .NET 10 introduces:

Obsolete Clipboard Methods

Some clipboard methods that depended on BinaryFormatter are now marked as obsolete, discouraging their use.

New JSON-Based Clipboard APIs

To replace the deprecated methods, .NET 10 introduces new APIs that allow clipboard data to be serialized and deserialized using JSON, eliminating the need for BinaryFormatter.

These changes enhance security and compatibility, while encouraging developers to adopt modern serialization techniques for clipboard operations.


Windows Forms in .NET 10 brings important updates to clipboard handling:

Obsolete clipboard methods discourage the use of BinaryFormatter.

New JSON-based APIs provide a modern and secure approach to clipboard serialization.

These improvements make Windows Forms applications more secure and future-proof, aligning with .NET’s long-term goals of improving safety and maintainability.


What’s New in WPF for .NET 10

Windows Presentation Foundation (WPF) in .NET 10 includes minor patches and bug fixes, focusing on stability, testing improvements, and cleanup of legacy security attributes.

While this release doesn’t introduce major new features, it enhances maintainability and reliability for WPF applications.


Testing and Stability Improvements

Expanded Unit Test Coverage

  • Over 4,000 new unit tests have been added for System.Xaml and WindowsBase, improving test coverage and ensuring greater reliability.

Fluent Theme Fixes

  • Resolved issues in the Fluent Theme, including a HighContrast mode crash that affected accessibility and UI consistency.

Code Access Security (CAS) Cleanup

.NET 10 continues the process of removing obsolete CAS-related code, streamlining WPF’s security model.

Key Changes:

  • Removed unused CAS resource strings and their translations from all libraries.
  • Removed outdated CAS and XBAP (XAML Browser Application) code from:
    • OleCmdHelper/ISecureCommand
    • FontSourceCollection/FontSource

These changes help reduce complexity and improve maintainability in the WPF codebase.


Breaking Changes in .NET 10

Migrating to .NET 10 may require adjustments due to breaking changes across various areas, including .NET Core libraries, globalization, cryptography, and Windows Forms.

Each change falls into one of the following categories:

🔴 Binary incompatible – Existing binaries may fail to load or execute in the new runtime, requiring recompilation.

🟡 Source incompatible – Code may need modifications to compile with the new SDK or runtime.

🟢 Behavioral change – Applications may behave differently at runtime, potentially requiring code updates.

Image description

.NET Core Libraries

API Deprecations with Non-Default Diagnostic IDs

  • Type: Source incompatible
  • Introduced in: Preview 1 Some API deprecations now use non-default diagnostic identifiers, which may require updates to suppress or handle warnings differently.

Changes to ActivitySource.CreateActivity and ActivitySource.StartActivity

  • Type: Behavioral change
  • Introduced in: Preview 1 The behavior of activity creation and starting has been adjusted to provide more consistent tracing behavior.

C# 14 Overload Resolution with Span<T> Parameters

  • Type: Behavioral change
  • Introduced in: Preview 1 Overload resolution in C# 14 now handles Span<T> and ReadOnlySpan<T> parameters differently, which may lead to method resolution changes in existing code.

Consistent Shift Behavior in Generic Math

  • Type: Behavioral change
  • Introduced in: Preview 1 Bitwise shift operations in generic math have been updated to ensure a consistent interpretation across platforms.

Stricter LDAP DirectoryControl Parsing

  • Type: Behavioral change
  • Introduced in: Preview 1 The parsing of LDAP DirectoryControl objects is now more strict, which may affect applications relying on less structured input data.

MacCatalyst Version Normalization

  • Type: Behavioral change
  • Introduced in: Preview 1 MacCatalyst versions are now normalized, ensuring a consistent versioning format when targeting this platform.

Globalization

Environment Variable Renamed to DOTNET_ICU_VERSION_OVERRIDE

  • Type: Behavioral change
  • Introduced in: Preview 1 The previous environment variable used to override ICU versions has been renamed, requiring updates in configurations that rely on it.

Cryptography

Stricter Validation for X500DistinguishedName

  • Type: Behavioral change
  • Introduced in: Preview 1 Parsing and validation of X500DistinguishedName now follow stricter security rules, potentially affecting applications that rely on more lenient validation.

Environment Variable Renamed to DOTNET_OPENSSL_VERSION_OVERRIDE

  • Type: Behavioral change
  • Introduced in: Preview 1 The environment variable for overriding OpenSSL versions has been renamed, requiring updates in system configurations.

Windows Forms

Renamed Parameter in HtmlElement.InsertAdjacentElement

  • Type: Source incompatible
  • Introduced in: Preview 1 A parameter in the InsertAdjacentElement method of HtmlElement has been renamed, which may require code updates where this method is used.

Checkbox Image Truncation in TreeView

  • Type: Behavioral change
  • Introduced in: Preview 1 The rendering of checkbox images in TreeView has changed, potentially affecting UI layouts.

Wrapping Up: .NET 10 Is Here to Stay!

With .NET 10, we’re getting a faster, smarter, and more efficient platform that’s ready for modern development challenges. Whether it’s runtime performance improvements, new C# 14 features, ASP.NET Core enhancements, or better tooling in the SDK, this release is packed with game-changing updates for developers.

As an LTS version, .NET 10 is a safe and reliable choice for production applications, ensuring long-term stability while still pushing the framework forward. If you haven’t already, give it a spin and see how it boosts your workflows and optimizes your applications.


But What About Security? 🔐

With all these new features and improvements, how are you handling security in your .NET applications? From code protection to secrets management, logs monitoring, and secure storage, ensuring that your software is protected is more important than ever.

ByteHide Security Solutions for .NET Developers

ByteHide Shield – Advanced obfuscation and runtime protection to keep your .NET code safe from reverse engineering.

ByteHide Secrets – Secure and manage secrets directly in your .NET applications.

ByteHide LogsReal-time logging and monitoring to detect threats and vulnerabilities.

ByteHide StorageEncrypted storage solutions for sensitive application data.

ByteHide MonitorProactive security insights to prevent threats before they happen.

Image description

.NET 10 brings tons of improvements, but at the end of the day, the best part of any new release is what developers build with it. 🛡️

Top comments (0)