UnsafeAccessorAttribute 类

定义

提供对特定类型的不可访问成员的访问权限。

public ref class UnsafeAccessorAttribute sealed : Attribute
[System.AttributeUsage(System.AttributeTargets.Method, AllowMultiple=false, Inherited=false)]
public sealed class UnsafeAccessorAttribute : Attribute
[<System.AttributeUsage(System.AttributeTargets.Method, AllowMultiple=false, Inherited=false)>]
type UnsafeAccessorAttribute = class
    inherit Attribute
Public NotInheritable Class UnsafeAccessorAttribute
Inherits Attribute
继承
UnsafeAccessorAttribute
属性

示例

public class Class
{
    static void StaticPrivateMethod() { }
    static int StaticPrivateField;
    Class(int i) { PrivateField = i; }
    void PrivateMethod() { }
    int PrivateField;
    int PrivateProperty { get => PrivateField; }
}

public void CallStaticPrivateMethod()
{
    StaticPrivateMethod(null);

    [UnsafeAccessor(UnsafeAccessorKind.StaticMethod, Name = nameof(StaticPrivateMethod))]
    extern static void StaticPrivateMethod(Class c);
}
public void GetSetStaticPrivateField()
{
    ref int f = ref GetSetStaticPrivateField(null);

    [UnsafeAccessor(UnsafeAccessorKind.StaticField, Name = "StaticPrivateField")]
    extern static ref int GetSetStaticPrivateField(Class c);
}
public void CallPrivateConstructor()
{
    Class c1 = PrivateCtor(1);

    Class c2 = (Class)RuntimeHelpers.GetUninitializedObject(typeof(Class));

    PrivateCtorAsMethod(c2, 2);

    [UnsafeAccessor(UnsafeAccessorKind.Constructor)]
    extern static Class PrivateCtor(int i);

    [UnsafeAccessor(UnsafeAccessorKind.Method, Name = ".ctor")]
    extern static void PrivateCtorAsMethod(Class c, int i);

}
public void CallPrivateMethod(Class c)
{
    PrivateMethod(c);

    [UnsafeAccessor(UnsafeAccessorKind.Method, Name = nameof(PrivateMethod))]
    extern static void PrivateMethod(Class c);
}
public void GetPrivateProperty(Class c)
{
    int f = GetPrivateProperty(c);

    [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "get_PrivateProperty")]
    extern static int GetPrivateProperty(Class c);
}
public void GetSetPrivateField(Class c)
{
    ref int f = ref GetSetPrivateField(c);

    [UnsafeAccessor(UnsafeAccessorKind.Field, Name = "PrivateField")]
    extern static ref int GetSetPrivateField(Class c);
}

// Generic example
public class Class<T>
{
    private T _field;
    private void M(T t) { }
    private void GM<U>(U u) { }
    private void GMWithConstraints<U, V>(U u, V v) where U : V, IEquatable<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(Class<V> c, V v);

    [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "GM")]
    public extern static void CallGM<X>(Class<V> c, X x);

    [UnsafeAccessor(UnsafeAccessorKind.Method, Name = "GMWithConstraints")]
    public extern static void CallGMWithConstraints<X, Y>(Class<V> c, X x, Y y) where X : Y, IEquatable<X>;
}

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

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

    Accessors<int>.CallGM<string>(c, string.Empty);

    Accessors<int>.CallGMWithConstraints<string, object>(c, string.Empty, new object());
}

注解

可以将此属性应用于 extern static 方法。 使用此属性批注的 extern static 方法的实现将由运行时根据属性中的信息以及应用特性的方法的签名提供。 运行时将尝试查找匹配的方法或字段,并将调用转发给它。 如果未找到匹配的方法或字段,则 extern static 方法的正文将引发 MissingFieldExceptionMissingMethodException

自 .NET 9 以来,支持泛型参数。 泛型参数必须与窗体和索引中的目标匹配(也就是说,类型参数必须是类型参数,方法参数必须是方法参数)。 extern static 方法的泛型参数还必须与目标上反映的任何约束完全匹配。 如果约束不匹配,该方法将引发 InvalidProgramException

对于 MethodStaticMethodFieldStaticField,带批注 extern static 方法的第一个参数的类型标识拥有类型。 仅检查定义的特定类型是否不可访问的成员。 类型层次结构不会进行查找匹配。

第一个参数的值被视为实例字段和方法的 this 指针。

对于结构上的实例字段和方法,第一个参数必须作为 ref 传递。

第一个参数的值不由实现用于 static 字段和方法使用,并且可以 null

如果需要设置字段,则可以 ref 访问器对字段的返回值。

可以使用 ConstructorMethod访问构造函数。

匹配通过比较 ECMA-335第 II.23.2 节中定义的元数据签名来确定。 返回类型被视为签名匹配项。 最初不考虑 Modreqs 和 modopts 进行签名匹配。 但是,如果存在不明确性忽略 modreqs 和 modopts,则会尝试精确匹配。 如果仍存在歧义,则会引发 AmbiguousMatchException

默认情况下,特性化方法的名称决定了方法/字段的名称。 在某些情况下,这可能会导致混淆,因为语言抽象(如 C# 本地函数)会生成杂乱的 IL 名称。 解决方法是使用 nameof 机制并定义 Name 属性。

构造函数

UnsafeAccessorAttribute(UnsafeAccessorKind)

实例化提供对类型 UnsafeAccessorKind成员的访问权限的 UnsafeAccessorAttribute

属性

Kind

获取向其提供访问权限的成员类型。

Name

获取或设置提供访问权限的成员的名称。

TypeId

在派生类中实现时,获取此 Attribute的唯一标识符。

(继承自 Attribute)

方法

Equals(Object)

返回一个值,该值指示此实例是否等于指定对象。

(继承自 Attribute)
GetHashCode()

返回此实例的哈希代码。

(继承自 Attribute)
GetType()

获取当前实例的 Type

(继承自 Object)
IsDefaultAttribute()

在派生类中重写时,指示此实例的值是否为派生类的默认值。

(继承自 Attribute)
Match(Object)

在派生类中重写时,返回一个值,该值指示此实例是否等于指定对象。

(继承自 Attribute)
MemberwiseClone()

创建当前 Object的浅表副本。

(继承自 Object)
ToString()

返回一个表示当前对象的字符串。

(继承自 Object)

适用于