Skip to content

Latest commit

 

History

History
104 lines (72 loc) · 4.65 KB

runtime.md

File metadata and controls

104 lines (72 loc) · 4.65 KB

.NET Runtime in .NET 9 Preview 4- Release Notes

Here's a summary of what's new in the .NET Runtime in this preview release:

Runtime updates in .NET 9 Preview 4:

.NET 9 Preview 4:

UnsafeAccessorAttribute supports generic parameters

The UnsafeAccessorAttribute feature allows unsafe access to type members that are unaccessible to the caller. This feature was designed in .NET 8 but implemented without support for generic parameters. In .NET 9, based on community feedback, we prioritized adding this support and it is now available for CoreCLR and native AOT scenarios. Remaining work, including support in mono, can be found here.

Usage example:

public class Class<T>
{
    private T _field;
    private void M<U>(T t, U u) { }
}

class Accessors<V>
{
    [UnsafeAccessor(UnsafeAccessorKind.Field, Name = "_field")]
    public extern static ref V GetSetPrivateField(Class<V> c);

    [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "M")]
    public extern static void CallM<W>(Class<V> c, V v, W w);
}

public void AccessGenericType(Class<int> c)
{
    ref int f = ref Accessors<int>.GetSetPrivateField(c);

    Accessors<int>.CallM<string>(c, 1, string.Empty);
}

Feature switches with trimming support

Two new attributes make it possible to define feature switches that can be used to toggle areas of functionality in .NET libraries, with support for removing unused features when trimming or native AOT compiling. For example, these attributes are used in the definitions of RuntimeFeature.IsDynamicCodeSupported and RuntimeFeature.IsDynamicCodeCompiled

FeatureSwitchDefinition

FeatureSwitchDefinitionAttribute can be used to treat a feature switch property as a constant when trimming:

public class Feature
{
    [FeatureSwitchDefinition("Feature.IsSupported")]
    internal static bool IsSupported => AppContext.TryGetSwitch("Feature.IsSupported", out bool isEnabled) ? isEnabled : true;

    internal static Implementation() => ...;
}

This allows dead code guarded by the switch to be removed. For example:

if (Feature.IsSupported)
    Feature.Implementation();

When the app is trimmed with the following feature settings, Feature.IsSupported is treated as false, and Feature.Implementation is removed.

<ItemGroup>
  <RuntimeHostConfigurationOption Include="Feature.IsSupported" Value="false" Trim="true" />
</ItemGroup>

FeatureGuard

FeatureGuardAttribute can be used to treat a feature switch property as a guard for code annotated with RequiresUnreferencedCodeAttribute, RequiresAssemblyFilesAttribute, or RequiresDynamicCodeAttribute:

public class Feature
{
    [FeatureGuard(typeof(RequiresDynamicCodeAttribute))]
    internal static bool IsSupported => RuntimeFeature.IsDynamicCodeSupported;

    [RequiresDynamicCode("Feature requires dynamic code support.")]
    internal static Implementation() => ...; // Uses dynamic code
}

Because the IsSupported property returns false whenever dynamic code is not supported, Feature.IsSupported can be used as a guard for methods that requires dynamic code at runtime. The FeatureGuardAttribute makes this known to the trim analyzer and the trimming tools. For example:

if (Feature.IsSupported)
    Feature.Implementation();

When built with <PublishAot>true</PublishAot>, the call to Feature.Implementation() will not produce analyzer warning IL3050, and Feature.Implementation will be removed when publishing.