// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. namespace System.Runtime.CompilerServices { /// <summary> /// Specifies the kind of target to which an <see cref="UnsafeAccessorAttribute" /> is providing access. /// </summary> public enum UnsafeAccessorKind { /// <summary> /// Provide access to a constructor. /// </summary> Constructor, /// <summary> /// Provide access to a method. /// </summary> Method, /// <summary> /// Provide access to a static method. /// </summary> StaticMethod, /// <summary> /// Provide access to a field. /// </summary> Field, /// <summary> /// Provide access to a static field. /// </summary> StaticField }; /// <summary> /// Provides access to an inaccessible member of a specific type. /// </summary> /// <remarks> /// This attribute may be applied to an <code>extern static</code> method. /// The implementation of the <code>extern static</code> method annotated with /// this attribute will be provided by the runtime based on the information in /// the attribute and the signature of the method that the attribute is applied to. /// The runtime will try to find the matching method or field and forward the call /// to it. If the matching method or field is not found, the body of the <code>extern</code> /// method will throw <see cref="MissingFieldException" /> or <see cref="MissingMethodException" />. /// Only the specific type defined will be examined for inaccessible members. The type hierarchy /// is not walked looking for a match. /// /// For <see cref="UnsafeAccessorKind.Method"/>, <see cref="UnsafeAccessorKind.StaticMethod"/>, /// <see cref="UnsafeAccessorKind.Field"/>, and <see cref="UnsafeAccessorKind.StaticField"/>, the type of /// the first argument of the annotated <code>extern</code> method identifies the owning type. /// The value of the first argument is treated as <code>this</code> pointer for instance fields and methods. /// The first argument must be passed as <code>ref</code> for instance fields and methods on structs. /// The value of the first argument is not used by the implementation for <code>static</code> fields and methods. /// /// Return type is considered for the signature match. modreqs and modopts are initially not considered for /// the signature match. However, if an ambiguity exists ignoring modreqs and modopts, a precise match /// is attempted. If an ambiguity still exists <see cref="System.Reflection.AmbiguousMatchException" /> is thrown. /// /// By default, the attributed method's name dictates the name of the method/field. This can cause confusion /// in some cases since language abstractions, like C# local functions, generate mangled IL names. The /// solution to this is to use the <code>nameof</code> mechanism and define the <see cref="Name"/> property. /// /// <code> /// public void Method(Class c) /// { /// PrivateMethod(c); /// /// [UnsafeAccessor(UnsafeAccessorKind.Method, Name = nameof(PrivateMethod))] /// extern static void PrivateMethod(Class c); /// } /// </code> /// </remarks> [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] public sealed class UnsafeAccessorAttribute : Attribute { // Block of text to include above when Generics support is added: // // The generic parameters of the <code>extern static</code> method are a concatenation of the type and // method generic arguments of the target method. For example, // <code>extern static void Method1<T1, T2>(Class1<T1> @this)</code> // can be used to call <code>Class1<T1>.Method1<T2>()</code>. The generic constraints of the // <code>extern static</code> method must match generic constraints of the target type, field or method. /// <summary> /// Instantiates an <see cref="UnsafeAccessorAttribute"/> providing access to a member of kind <see cref="UnsafeAccessorKind"/>. /// </summary> /// <param name="kind">The kind of the target to which access is provided.</param> public UnsafeAccessorAttribute(UnsafeAccessorKind kind) => Kind = kind; /// <summary> /// Gets the kind of member to which access is provided. /// </summary> public UnsafeAccessorKind Kind { get; } /// <summary> /// Gets or sets the name of the member to which access is provided. /// </summary> /// <remarks> /// The name defaults to the annotated method name if not specified. /// The name must be unset/<code>null</code> for <see cref="UnsafeAccessorKind.Constructor"/>. /// </remarks> public string? Name { get; set; } } } |