Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/variables/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#:在运行时获取值类型变量的大小? 我知道C和C++这样的语言允许在运行时使用siZeFo()函数确定数据的大小(结构、数组、变量…)。我在C#中尝试过,显然它不允许将变量放入sizeof()函数,但只允许类型定义(float、byte、Int32、uint等),我该怎么做_C#_Variables_Runtime_Value Type - Fatal编程技术网

C#:在运行时获取值类型变量的大小? 我知道C和C++这样的语言允许在运行时使用siZeFo()函数确定数据的大小(结构、数组、变量…)。我在C#中尝试过,显然它不允许将变量放入sizeof()函数,但只允许类型定义(float、byte、Int32、uint等),我该怎么做

C#:在运行时获取值类型变量的大小? 我知道C和C++这样的语言允许在运行时使用siZeFo()函数确定数据的大小(结构、数组、变量…)。我在C#中尝试过,显然它不允许将变量放入sizeof()函数,但只允许类型定义(float、byte、Int32、uint等),我该怎么做,c#,variables,runtime,value-type,C#,Variables,Runtime,Value Type,实际上,我希望这种情况发生: int x; Console.WriteLine(sizeof(x)); // Output: 4 而不是: Console.WriteLine(sizeof(int)); // Output: 4 我相信在C#中有一些正常的方法可以在运行时获得数据大小,但google并没有提供太多帮助。。这是我最后的希望,int的大小总是32位。为什么需要在运行时获取大小 话虽如此,您可以使用,但这实际上只适用于非托管的代码 我认为这显然会给你一个值类型的大小。它使用反射

实际上,我希望这种情况发生:

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

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

我相信在C#中有一些正常的方法可以在运行时获得数据大小,但google并没有提供太多帮助。。这是我最后的希望,int的大小总是32位。为什么需要在运行时获取大小

话虽如此,您可以使用,但这实际上只适用于非托管的代码

我认为这显然会给你一个值类型的大小。它使用反射,与您想要使用的功能(
sizeof()
)相比,它将是一个非常昂贵的方法调用:

使用系统;
运用系统反思;
使用System.Reflection.Emit;
...
//GetManagedSize()返回其类型为
//是存储在托管内存中的“类型”。对于任何引用类型
//这将简单地返回指针的大小(4或8)。
公共静态int-GetManagedSize(类型)
{
//所有这些只是为了调用一个操作码而没有参数!
var方法=新的DynamicMethod(“GetManagedSizeImpl”,typeof(uint),新类型[0],typeof(TypeExtensions),false);
ILGenerator=method.GetILGenerator();
gen.Emit(操作码.Sizeof,类型);
gen.Emit(操作码Ret);
var func=(func)method.CreateDelegate(typeof(func));
返回选中((int)func());
}

要在运行时查找任意变量的大小,
x
,可以使用:


正如dtb所提到的,此函数在编组后返回变量的大小,但根据我的经验,这通常是您想要的大小,因为在纯托管环境中,变量的大小没有什么意义。

我想说的是,使用类型推断来满足您的要求(“如果将x的类型从int改为long long,则不必将每次出现的sizeof(int)都替换为sizeof(long long)”:

从下面开始,如果性能很重要,并且您需要经常访问此代码,那么您可以缓存大小,以便动态方法只需要为每种类型构建和执行一次:

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();
        }
    }
}
intx=42;
Console.WriteLine(Utils.SizeOf(x));//输出:4
// ...
公共静态类Utils
{
公共静态int SizeOf(T obj)
{
返回SizeOfCache.SizeOf;
}
私有静态类SizeOfCache
{
公共静态只读int-SizeOf;
静态SizeOfCache()
{
var dm=新的动态方法(“func”,typeof(int),
Type.EmptyTypes,typeof(Utils));
ILGenerator il=dm.GetILGenerator();
il.Emit(opcode.Sizeof,typeof(T));
发射(操作码Ret);
var func=(func)dm.CreateDelegate(typeof(func));
SizeOf=func();
}
}
}

如果您正在执行类似于构建数据包以发送到设备的操作,请尝试以下操作:

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

例如,现在您可以将dataBytes数组复制到dataPacket数组的Payload部分,dataLength将告诉您要复制多少字节,并允许您验证或设置数据包中的PayloadLength值。

继续,并为CORY发布的代码添加了一些安全/性能/便利功能,以减少偏执的LukeH的代码应该足够了

简而言之,该类返回类型大小,确保尽可能使用缓存,并在运行时包装外部类的异常

您可能需要重写catch-all块以更好地适应您的项目

/* 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;
}
/*用于查找类型和变量大小的类*/
公共静态班级规模
{
/*检索泛型类型T的大小
成功返回“T”的大小,否则返回0*/
公共静态int-SizeOf()
{
返回FetchSizeOf(typeof(T));
}
/*检索对象类型的大小
成功返回“obj”的大小,否则返回0*/
公共静态int SizeOf(T obj)
{
返回FetchSizeOf(typeof(T));
}
/*检索“类型”的大小
成功返回“type”的大小,否则返回0*/
公共静态int-SizeOf(此类型)
{
返回FetchSizeOf(类型);
}
/*获取指定类型的大小
成功返回“type”的大小,否则返回0*/
私有静态int-FetchSizeOf(此类型)
{
if(typeSizeCache==null)
CreateCache();
if(typeSizeCache!=null)
{
int size=0;
if(GetCachedSizeOf(类型,输出大小))
返回大小;
其他的
返回CalcAndCacheSizeOf(类型);
}
其他的
返回CalcSizeOf(类型);
}
/*尝试从缓存中获取类型的大小
返回true并设置成功时的大小,返回
false,否则将大小设置为0*/
私有静态bool GetCachedSizeOf(类型类型,out int size)
{
尺寸=0;
尝试
{
if(type!=null)
{
如果(!typeSizeCache.TryGetValue(类型,超出大小))
尺寸=0;
}
}
抓住
{
/*-记录:异常
-没有关键的例外*/
尺寸=0;
}
返回大小>0;
}
/*尝试计算“类型”和缓存的大小
大小(如果有效)(大小>0)
成功时返回计算的大小,否则返回0*/
私有静态int CalcAndCacheSizeOf(类型)
{
int-typeSize=0;
尝试
{
typeSize=CalcSizeOf(类型);
如果(字体大小>0)
字号
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));
    }
}
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();
        }
    }
}
byte[] dataBytes = BitConverter.GetBytes(x);
int dataLength= dataBytes.Length;
/* 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;
}
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[0]);
            ILGenerator il = dm.GetILGenerator();
            il.Emit(OpCodes.Sizeof, type);
            il.Emit(OpCodes.Ret);
            return (int)dm.Invoke(null, null);
        });
    }
}