Metalama 2026.0 brings full support for C# 14, the most significant evolution of the C# language in many years.
Highlights:
- C# 14 and .NET 10 SDK support, including extension blocks, partial constructors, partial events, and compound assignment operators
- First-class tuple types with direct access to element names and types
- Event handler invocation overriding for implementing patterns like safe events
- Faster Visual Studio experience with significant performance improvements
Metalama 2026.0 ensures you're ready to take full advantage of the latest C# features while keeping your aspects clean, powerful, and maintainable.
Requirements
Development environment
Metalama 2026.0 supports the following development environments and SDKs:
- Visual Studio:
- 2022 LTSC 17.12 (latest build)
- 2022 17.14 (latest build)
- 2026 18.0 (latest build)
- .NET SDK 8.0, 9.0, or 10.0.
- C# 12, 13, or 14.
Warning
.NET 6 SDK has been deprecated in this release (#1092).
Target frameworks (runtimes)
Metalama 2026.0 supports the following target frameworks:
- Metalama.Framework and Metalama.Extensions: any framework implementing the .NET Standard 2.0 API (language polyfills might be required for some frameworks, see for instance PolySharp).
- Metalama.Patterns: .NET Framework 4.7.2 (tested), .NET 8.0 (tested), or any framework implementing the .NET Standard 2.0 API (untested).
Warning
.NET 6 has been deprecated as a tested runtime.
C# 14 support
Metalama 2026.0 provides extensive support for C# 14 language features. While most features are fully implemented, some remain on the roadmap for future releases.
Implemented in 2026.0
Metalama 2026.0 supports the following C# 14 features:
- #1108: Use null-conditional assignments when generating syntax from an IFieldOrPropertyOrIndexer (when assigning their
Valueproperty). Use the WithOptions and specifyNullConditional. - #1094: Override a property that uses the
fieldkeyword. - #1110: Override or introduce to a partial constructor.
- #1111: Add an instance initializer to a partial constructor.
- #1112: Introduce partial events.
- #1113: Override partial events.
- #1034: Query extension blocks and extension members from the code model (see below).
- #1035: Override members of extension blocks.
- #1115: Query compound assignment operators in the code model.
- #1116: Override compound assignment operators.
- #1160: Introduce new extension members into existing extension blocks.
- #1041: Use simple lambda parameters with modifiers both in compile-time and run-time code.
- #1105: When an unsupported feature is used in a template, an understandable error message is reported.
Limitations
The following C# 14 features haven't been implemented in Metalama 2026.0:
- #1109: Use null-conditional assignments in templates.
- #1114: Use the
fieldkeyword in templates. - #1036: Generate run-time code for extension members using invoker interfaces.
- #1127: Add a contract to the receiver parameter of extension blocks.
- #1131: Introducing new compound assignment operators.
- #1143: Introducing parameters into partial constructors.
- #1159: Introducing new extension blocks.
Extension blocks
Extension blocks represent the flagship feature of C# 14, enabling the extension of any type with new members. Metalama 2026.0 provides comprehensive support for extension blocks, including the ability to override extension members.
Extension blocks are modeled using the IExtensionBlock interface, which derives from INamedType with the following characteristics:
- DeclarationKind is
Extensionand TypeKind isExtension. - Adds ReceiverParameter and ReceiverType properties.
- For extension members (excluding classic extension methods), IMember.DeclaringType references the IExtensionBlock.
Warning
Although IExtensionBlock implements INamedType, an extension block cannot be used as an IType. This behavior breaks the Liskov Substitution Principle, but it is much simpler than changing the type of IMember.DeclaringType property.
Extension blocks are accessible through INamedType.ExtensionBlocks, not as nested types in INamedType.Types.
Extension methods and property accessors are available in INamedType.Methods as implicitly-implemented methods. These methods exist in IL and are addressable in C#, but cannot be overridden with Metalama.
This implementation aligns closely with Roslyn's model, providing a natural experience for C# developers.
First-class support for tuple types
Metalama 2026.0 introduces first-class support for named tuples through the new ITupleType interface. Previously, tuples were treated as plain INamedType objects without access to element types or names, making scenarios such as argument packing for interceptors cumbersome and inefficient.
The new implementation provides direct access to element names and types through TypeFactory.CreateTupleType for creation, and ITupleType.CreateCreateInstanceExpression for instantiation.
The implementation supports tuples with any number of elements:
- For tuples with two or more elements: native tuple syntax
- For degenerate cases (zero or one element): automatic fallback to
ValueTuple.Create(...)
For details, see Working with types.
Event handler invocation overriding
Metalama 2026.0 introduces the capability to override event handler invocations (#549). This extends the existing functionality that allowed overriding only the add and remove operations of events.
This advice kind allows you to implement aspects such as "safe events", where event handlers are isolated from each other by an exception handler.
For comprehensive documentation, see Overriding events.
Visual Studio Tools for Metalama: performance improvements
Visual Studio Tools for Metalama includes refactored components that dramatically improve performance. It's now more stable, consumes less CPU, and makes better use of your cores.
Additional improvements
Toast notifications for product news (#1161). Visual Studio Tools for Metalama can now display toast notifications when new blog posts or product briefs are published.
User-defined checked operators (#1133). Metalama 2026.0 adds support for introducing user-defined
checkedoperators.Cross-project dependency injection (#568). Enhanced dependency injection capabilities now allow pulling constructor parameters across project boundaries. See Injecting dependencies into aspects.
Compile-time assembly resolver (#1088). The component that downloads compile-time assembly now properly respects the project's
nuget.configfile for package resolution.Single-file dotnet run support (#1107). Metalama now supports Microsoft's single-file
dotnet runfunctionality, allowing aspects to work with modern .NET single-file deployment scenarios.ExcludeAspect enhancement (#1176). The
[ExcludeAspect]attribute, when applied to a field or property, now implicitly applies to its accessors.
Documentation updates
- New article: Working with types.
- Improved the chapter: Writing T# templates.
- Improved the API documentation by adding elements from the conceptual documentation where relevant.
- Claude Code skill: A new skill package is available to enhance Claude Code with Metalama-specific knowledge. See Configuring Claude Code for installation instructions.
Breaking changes
- INamedType.TypeKind now returns
Tupleinstead ofNamedTypefor tuples. - IAspectBuilder.Advice is now obsolete. Use IAdviser instead.
- The With method has been split into WithObject and WithOptions with additional overloads. This change applies to all kinds of members.
- IAdviser and AdviserExtensions have been moved to the
Metalama.Framework.Aspectsnamespace. TypeKind.RecordClassandTypeKind.RecordStructhave been removed and replaced by INamedType.IsRecord.- The
IntroduceConversionOperatormethod now has an additional optional parameter to supportcheckedoperators. - ServiceLocator self-registration removed: The Metalama.Extensions.DependencyInjection.ServiceLocator adapter no longer automatically registers itself via a TransitiveProjectFabric. Projects using this adapter must now explicitly register the ServiceLocatorDependencyInjectionFramework it in their ProjectFabric.
- Elvis operator behavior change in templates: The null-conditional operator (
?.) is no longer simplified for non-nullable reference types in templates. It is still simplified for non-nullable value types. This may result in different generated code compared to previous versions. - Test framework changes: The
@AcceptInvalidInputand@ReportOutputWarningsdirectives have been removed; both behaviors are now enabled by default.