Condividi tramite


UnsafeAccessorAttribute Classe

Definizione

Fornisce l'accesso a un membro inaccessibile di un tipo specifico.

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
Ereditarietà
UnsafeAccessorAttribute
Attributi

Esempio

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());
}

Commenti

È possibile applicare questo attributo a un metodo extern static. L'implementazione del metodo extern static annotata con questo attributo verrà fornita dal runtime in base alle informazioni contenute nell'attributo e alla firma del metodo a cui viene applicato l'attributo. Il runtime tenterà di trovare il metodo o il campo corrispondente e inoltrare la chiamata. Se il metodo o il campo corrispondente non viene trovato, il corpo del metodo extern static genererà MissingFieldException o MissingMethodException.

I parametri generici sono supportati a partire da .NET 9. I parametri generici devono corrispondere alla destinazione nel formato e nell'indice, ovvero i parametri di tipo devono essere parametri di tipo e i parametri del metodo devono essere parametri del metodo. I parametri generici del metodo extern static devono corrispondere esattamente a tutti i vincoli che si riflettono sulla destinazione. Se i vincoli non corrispondono, il metodo genera InvalidProgramException.

Per Method, StaticMethod, Fielde StaticField, il tipo del primo argomento del metodo extern static con annotazioni identifica il tipo proprietario. Solo il tipo specifico definito verrà esaminato per i membri inaccessibili. La gerarchia dei tipi non viene esaminata cercando una corrispondenza.

Il valore del primo argomento viene considerato come this puntatore per i campi e i metodi dell'istanza.

Il primo argomento deve essere passato come ref per i campi e i metodi di istanza negli struct.

Il valore del primo argomento non viene usato dall'implementazione per static campi e metodi e può essere null.

Il valore restituito per una funzione di accesso a un campo può essere ref se si desidera impostare il campo.

È possibile accedere ai costruttori usando Constructor o Method.

Una corrispondenza viene determinata confrontando le firme dei metadati definite nella sezione II.23.2 di ECMA-335. Il tipo restituito viene considerato per la corrispondenza della firma. Modreqs e modopts inizialmente non vengono considerati per la corrispondenza della firma. Tuttavia, se esiste un'ambiguità ignorando modreqs e modopts, viene tentata una corrispondenza precisa. Se esiste ancora un'ambiguità, viene generata AmbiguousMatchException.

Per impostazione predefinita, il nome del metodo con attributi determina il nome del metodo/campo. Ciò può causare confusione in alcuni casi, poiché le astrazioni del linguaggio, ad esempio le funzioni locali C#, generano nomi IL mangled. La soluzione consiste nell'usare il meccanismo di nameof e definire la proprietà Name.

Costruttori

UnsafeAccessorAttribute(UnsafeAccessorKind)

Crea un'istanza di un UnsafeAccessorAttribute fornendo l'accesso a un membro di tipo UnsafeAccessorKind.

Proprietà

Kind

Ottiene il tipo di membro a cui viene fornito l'accesso.

Name

Ottiene o imposta il nome del membro a cui viene fornito l'accesso.

TypeId

Se implementato in una classe derivata, ottiene un identificatore univoco per questo Attribute.

(Ereditato da Attribute)

Metodi

Equals(Object)

Restituisce un valore che indica se questa istanza è uguale a un oggetto specificato.

(Ereditato da Attribute)
GetHashCode()

Restituisce il codice hash per questa istanza.

(Ereditato da Attribute)
GetType()

Ottiene il Type dell'istanza corrente.

(Ereditato da Object)
IsDefaultAttribute()

Quando sottoposto a override in una classe derivata, indica se il valore di questa istanza è il valore predefinito per la classe derivata.

(Ereditato da Attribute)
Match(Object)

Quando sottoposto a override in una classe derivata, restituisce un valore che indica se questa istanza è uguale a un oggetto specificato.

(Ereditato da Attribute)
MemberwiseClone()

Crea una copia superficiale del Objectcorrente.

(Ereditato da Object)
ToString()

Restituisce una stringa che rappresenta l'oggetto corrente.

(Ereditato da Object)

Si applica a