UnsafeAccessorAttribute Clase
Definición
Importante
Parte de la información hace referencia a la versión preliminar del producto, que puede haberse modificado sustancialmente antes de lanzar la versión definitiva. Microsoft no otorga ninguna garantía, explícita o implícita, con respecto a la información proporcionada aquí.
Proporciona acceso a un miembro inaccesible de un tipo específico.
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
- Herencia
- Atributos
Ejemplos
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());
}
Comentarios
Puede aplicar este atributo a un método extern static
. El tiempo de ejecución proporcionará la implementación del método extern static
anotado con este atributo en función de la información del atributo y la firma del método al que se aplica el atributo. El tiempo de ejecución intentará buscar el método o campo coincidente y reenviará la llamada a él. Si no se encuentra el método o campo coincidente, el cuerpo del método extern static
producirá MissingFieldException o MissingMethodException.
Se admiten parámetros genéricos desde .NET 9. Los parámetros genéricos deben coincidir con el destino en forma e índice (es decir, los parámetros de tipo deben ser parámetros de tipo y los parámetros de método deben ser parámetros de método). Los parámetros genéricos del método extern static
también deben coincidir exactamente con las restricciones reflejadas en el destino. Si las restricciones no coinciden, el método produce InvalidProgramException.
Para Method, StaticMethod, Fieldy StaticField, el tipo del primer argumento del método anotado extern static
identifica el tipo propietario. Solo se examinará el tipo específico definido para los miembros inaccesibles. La jerarquía de tipos no se recorre buscando una coincidencia.
El valor del primer argumento se trata como this
puntero para los campos y métodos de instancia.
El primer argumento debe pasarse como ref
para campos y métodos de instancia en estructuras.
La implementación no usa el valor del primer argumento para static
campos y métodos y puede ser null
.
El valor devuelto de un descriptor de acceso a un campo puede ser ref
si se desea establecer el campo.
Se puede acceder a los constructores mediante Constructor o Method.
Una coincidencia se determina comparando las firmas de metadatos tal como se define en la sección II.23.2 de ECMA-335. El tipo de valor devuelto se considera para la coincidencia de firma. Los modreqs y los modopts no se consideran inicialmente para la coincidencia de firma. Sin embargo, si existe una ambigüedad que omite modreqs y modopts, se intenta realizar una coincidencia precisa. Si todavía existe una ambigüedad, se produce AmbiguousMatchException.
De forma predeterminada, el nombre del método con atributos dicta el nombre del método o campo. Esto puede causar confusión en algunos casos, ya que las abstracciones de lenguaje, como las funciones locales de C#, generan nombres il mangled. La solución a esto consiste en usar el mecanismo de nameof
y definir la propiedad Name.
Constructores
UnsafeAccessorAttribute(UnsafeAccessorKind) |
Crea una instancia de un UnsafeAccessorAttribute que proporciona acceso a un miembro de tipo UnsafeAccessorKind. |
Propiedades
Kind |
Obtiene el tipo de miembro al que se proporciona acceso. |
Name |
Obtiene o establece el nombre del miembro al que se proporciona acceso. |
TypeId |
Cuando se implementa en una clase derivada, obtiene un identificador único para este Attribute. (Heredado de Attribute) |
Métodos
Equals(Object) |
Devuelve un valor que indica si esta instancia es igual a un objeto especificado. (Heredado de Attribute) |
GetHashCode() |
Devuelve el código hash de esta instancia. (Heredado de Attribute) |
GetType() |
Obtiene el Type de la instancia actual. (Heredado de Object) |
IsDefaultAttribute() |
Cuando se reemplaza en una clase derivada, indica si el valor de esta instancia es el valor predeterminado de la clase derivada. (Heredado de Attribute) |
Match(Object) |
Cuando se reemplaza en una clase derivada, devuelve un valor que indica si esta instancia es igual a un objeto especificado. (Heredado de Attribute) |
MemberwiseClone() |
Crea una copia superficial del Objectactual. (Heredado de Object) |
ToString() |
Devuelve una cadena que representa el objeto actual. (Heredado de Object) |