visual ultima studio novedades new features español c# .net visual-studio cil

ultima - c# 8



¿Cuál es la diferencia entre sizeof(T) y Unsafe.SizeOf<T>()? (1)

Si bien este método solo utiliza el sizeof instrucción IL, existe una diferencia con el operador de sizeof normal, porque este operador no se puede aplicar a tipos arbitrarios:

Se utiliza para obtener el tamaño en bytes para un tipo no administrado. Los tipos no administrados incluyen los tipos incorporados que se enumeran en la tabla que sigue, y también lo siguiente:

Tipos de Enum

Tipos de puntero

Estructuras definidas por el usuario que no contienen ningún campo o propiedad que sean tipos de referencia

Si intentas escribir un análogo de Unsafe.SizeOf , no funcionará:

public static int SizeOf<T>() { // nope, will not compile return sizeof(T); }

So Unsafe.SizeOf levanta las restricciones de Unsafe.SizeOf del operador y le permite usar instrucciones de tamaño de IL de tipos arbitrarios (incluidos los tipos de referencia para los que devolverá el tamaño de referencia).

En cuanto a la construcción de atributos que se ve en IL, eso no significa que los atributos se instanciarán para cada llamada, eso es solo la sintaxis de IL para asociar atributos con varios miembros (método en este caso).

Ejemplos:

public struct Test { public int Int1; } static void Main() { // works var s1 = Unsafe.SizeOf<Test>(); // doesn''t work, need to mark method with "unsafe" var s2 = sizeof(Test); }

Otro ejemplo:

public struct Test { public int Int1; public string String1; } static unsafe void Main() { // works, return 16 in 64bit process - 4 for int, 4 for padding, because // alignment of the type is the size of its largest element, which is 8 // and 8 for string var s1 = Unsafe.SizeOf<Test>(); // doesn''t work even with unsafe, // cannot take size of variable of managed type "Test" // because Test contains field of reference type (string) var s2 = sizeof(Test); }

En primer lugar, un pequeño aviso legal antes de la pregunta real:

Sé que hay muchas preguntas cerradas / duplicadas con respecto a la diferencia entre el sizeof operador y el Marshal.SizeOf<T> , y entiendo la diferencia entre los dos. Aquí estoy hablando del SizeOf<T> en la nueva clase Unsafe

Por lo tanto, no estoy seguro de entender la diferencia real entre estas dos operaciones, y si existe una diferencia específica al usar el método en una estructura / clase en particular.

El operador sizeof toma un nombre de tipo y devuelve el número de bytes administrados que se supone que debe ocupar cuando se lo asigna (es decir, un Int32 devolverá 4, por ejemplo).

El Unsafe.SizeOf<T> , por otro lado, se implementa en IL como todos los otros métodos en la clase de Unsafe , y mirando el código, esto es lo que hace:

.method public hidebysig static int32 SizeOf<T>() cil managed aggressiveinlining { .custom instance void System.Runtime.Versioning.NonVersionableAttribute::.ctor() = ( 01 00 00 00 ) .maxstack 1 sizeof !!T ret }

Ahora, si no me equivoco, ¡el código está llamando a sizeof !!T que es lo mismo que sizeof(T) (llamando al operador sizeof con el nombre de tipo T ), por lo que no serían exactamente equivalentes ?

Además, veo que el método también está asignando un objeto inútil (el NonVersionableAttribute ) en la primera línea, así que, ¿no causaría eso que una pequeña cantidad de memoria se asigne también?

Mi pregunta es:

¿Es seguro decir que los dos métodos son perfectamente equivalentes y que, por lo tanto, es mejor usar el operador clásico de sizeof , ya que eso también evita la asignación de ese atributo en el SizeOf<T> ? ¿Se SizeOf<T> este SizeOf<T> a la clase Unsafe solo por conveniencia en este momento?