tipos tipo numericas funciones ejemplos datos dato conversion c# variables runtime value-type

numericas - C#: ¿Obtener el tamaño de una variable de tipo de valor en tiempo de ejecución?



tipos de variables numericas en c# (7)

De acuerdo con la respuesta de Cory , si el rendimiento es importante y necesita golpear mucho este código, puede almacenar el tamaño en la memoria caché para que el método dinámico solo deba crearse y ejecutarse una vez por tipo:

int x = 42; Console.WriteLine(Utils.SizeOf(x)); // Output: 4 // ... public static class Utils { public static int SizeOf<T>(T obj) { return SizeOfCache<T>.SizeOf; } private static class SizeOfCache<T> { public static readonly int SizeOf; static SizeOfCache() { var dm = new DynamicMethod("func", typeof(int), Type.EmptyTypes, typeof(Utils)); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Sizeof, typeof(T)); il.Emit(OpCodes.Ret); var func = (Func<int>)dm.CreateDelegate(typeof(Func<int>)); SizeOf = func(); } } }

Sé que lenguajes como C y C ++ permiten determinar el tamaño de los datos (estructuras, matrices, variables ...) en tiempo de ejecución utilizando la función sizeof (). Lo intenté en C # y aparentemente no permite poner variables en la función sizeof (), sino solo las definiciones de tipo (float, byte, Int32, uint, etc ...), ¿cómo se supone que debo hacer eso?

En la práctica, quiero que esto suceda:

int x; Console.WriteLine(sizeof(x)); // Output: 4

Y NO:

Console.WriteLine(sizeof(int)); // Output: 4

Estoy seguro de que hay una manera normal de obtener el tamaño de los datos en tiempo de ejecución en C #, sin embargo, Google no brindó mucha ayuda ... Aquí está mi última esperanza


El tamaño de int siempre va a ser de 32 bits. ¿Por qué necesitarías obtener el tamaño en tiempo de ejecución?

Con eso dicho, podrías usar Marshal.SizeOf() , pero en realidad está destinado solo para código no administrado .

Me encontré con un código que aparentemente le dará el tamaño de un tipo de valor. Utiliza la reflexión y sería un método bastante costoso en comparación con la funcionalidad que querías usar ( sizeof() ):

using System; using System.Reflection; using System.Reflection.Emit; ... // GetManagedSize() returns the size of a structure whose type // is ''type'', as stored in managed memory. For any referenec type // this will simply return the size of a pointer (4 or 8). public static int GetManagedSize(Type type) { // all this just to invoke one opcode with no arguments! var method = new DynamicMethod("GetManagedSizeImpl", typeof(uint), new Type[0], typeof(TypeExtensions), false); ILGenerator gen = method.GetILGenerator(); gen.Emit(OpCodes.Sizeof, type); gen.Emit(OpCodes.Ret); var func = (Func<uint>)method.CreateDelegate(typeof(Func<uint>)); return checked((int)func()); }


Iba a decir que se debe usar la inferencia de tipos para cumplir con sus requisitos ("si cambia el tipo de x de int para decir long long, no tiene que reemplazar cada aparición de sizeof (int) con sizeof (long))") :

public unsafe void GetSizeOf<T>(T exemplar) where T : struct { return sizeof(T); }

Pero no puede hacer eso, porque T podría ser un "tipo administrado", podría ser una estructura con un campo de referencia de objeto. No parece haber una forma de restringir T a solo tipos no administrados.

Podrías usar una clase de ayuda estática:

public static class Size { public int Of(int x) { return sizeof(int); } public int Of(long x) { return sizeof(long); } public unsafe int Of(MyStruct x) { //only works if MyStruct is unmanaged return sizeof(MyStruct); } } public class Program { public void Main() { int x = 0; Console.WriteLine(Size.Of(x)); } public void OldMain() { long x = 0; Console.WriteLine(Size.Of(x)); } }


Para encontrar el tamaño de una variable arbitraria, x , en tiempo de ejecución puede usar Marshal.SizeOf :

System.Runtime.InteropServices.Marshal.SizeOf(x)

Como lo menciona dtb, esta función devuelve el tamaño de la variable después de la ordenación , pero en mi experiencia, generalmente es el tamaño que desea, ya que en un entorno de administración pura, el tamaño de una variable es de poco interés.


Se adelantó y agregó algunas características de seguridad / rendimiento / conveniencia al código CORY publicado, ya que el código de LukeH, menos paranoico, debería ser suficiente.

En resumen, esta clase devuelve tamaños de tipo, asegurando que se use un caché siempre que sea posible, completando las excepciones de clases externas a medida que avanza.

Es posible que desee volver a escribir los bloques de captura para adaptarse mejor a su proyecto.

/* A class for finding the sizes of types and variables */ public static class Sizes { /* Retrieves the size of the generic type T Returns the size of ''T'' on success, 0 otherwise */ public static int SizeOf<T>() { return FetchSizeOf(typeof(T)); } /* Retrieves the size of the type of obj Returns the size of ''obj'' on success, 0 otherwise */ public static int SizeOf<T>(T obj) { return FetchSizeOf(typeof(T)); } /* Retrieves the size of ''type'' Returns the size of ''type'' on success, 0 otherwise */ public static int SizeOf(this Type type) { return FetchSizeOf(type); } /* Gets the size of the specified type Returns the size of ''type'' on success, 0 otherwise*/ private static int FetchSizeOf(this Type type) { if ( typeSizeCache == null ) CreateCache(); if ( typeSizeCache != null ) { int size = 0; if ( GetCachedSizeOf(type, out size) ) return size; else return CalcAndCacheSizeOf(type); } else return CalcSizeOf(type); } /* Attempts to get the size of type from the cache Returns true and sets size on success, returns false and sets size to 0 otherwise. */ private static bool GetCachedSizeOf(Type type, out int size) { size = 0; try { if ( type != null ) { if ( !typeSizeCache.TryGetValue(type, out size) ) size = 0; } } catch { /* - Documented: ArgumentNullException - No critical exceptions. */ size = 0; } return size > 0; } /* Attempts to calculate the size of ''type'', and caches the size if it is valid (size > 0) Returns the calclated size on success, 0 otherwise */ private static int CalcAndCacheSizeOf(Type type) { int typeSize = 0; try { typeSize = CalcSizeOf(type); if ( typeSize > 0 ) typeSizeCache.Add(type, typeSize); } catch { /* - Documented: ArgumentException, ArgumentNullException, - Additionally Expected: OutOfMemoryException - No critical exceptions documented. */ } return typeSize; } /* Calculates the size of a type using dynamic methods Return the type''s size on success, 0 otherwise */ private static int CalcSizeOf(this Type type) { try { var sizeOfMethod = new DynamicMethod("SizeOf", typeof(int), Type.EmptyTypes); var generator = sizeOfMethod.GetILGenerator(); generator.Emit(OpCodes.Sizeof, type); generator.Emit(OpCodes.Ret); var sizeFunction = (Func<int>)sizeOfMethod.CreateDelegate(typeof(Func<int>)); return sizeFunction(); } catch { /* - Documented: OutOfMemoryException, ArgumentNullException, ArgumentException, MissingMethodException, MethodAccessException - No critical exceptions documented. */ } return 0; } /* Attempts to allocate the typeSizesCache returns whether the cache is allocated*/ private static bool CreateCache() { if ( typeSizeCache == null ) { try { typeSizeCache = new Dictionary<Type, int>(); } catch { /* - Documented: OutOfMemoryException - No critical exceptions documented. */ typeSizeCache = null; } } return typeSizeCache != null; } /* Static constructor for Sizes, sets typeSizeCache to null */ static Sizes() { CreateCache(); } /* Caches the calculated size of various types */ private static Dictionary<Type, int> typeSizeCache; }


Si está haciendo algo como crear paquetes de datos para enviar a un dispositivo, intente esto:

byte[] dataBytes = BitConverter.GetBytes(x); int dataLength= dataBytes.Length;

Ahora, por ejemplo, puede copiar la matriz dataBytes en la sección de Carga útil de la matriz dataPacket, y dataLength le dirá cuántos bytes copiar, y le permitirá validar o establecer el valor de PayloadLength en su paquete de datos.


public static class TypeSize { public static int GetSize<T>(this T value) { if (typeof(T).IsArray) { var elementSize = GetTypeSize(typeof(T).GetElementType()); var length = (value as Array)?.GetLength(0); return length.GetValueOrDefault(0) * elementSize; } return GetTypeSize(typeof(T)); } static ConcurrentDictionary<Type, int> _cache = new ConcurrentDictionary<Type, int>(); static int GetTypeSize(Type type) { return _cache.GetOrAdd(type, _ => { var dm = new DynamicMethod("SizeOfType", typeof(int), new Type[] { }); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Sizeof, _); il.Emit(OpCodes.Ret); return (int)dm.Invoke(null, null); }); } }