C#:在运行时获取值类型变量的大小?

Gio*_*der 21 c# variables runtime value-type

我知道C和C++等语言允许在运行时使用sizeof()函数确定数据的大小(结构,数组,变量......).我在C#中尝试过,显然它不允许将变量放入sizeof()函数中,但只键入defintions(float,byte,Int32,uint等等),我该怎么做呢?

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

int x;
Console.WriteLine(sizeof(x));   // Output: 4
Run Code Online (Sandbox Code Playgroud)

并不是:

Console.WriteLine(sizeof(int)); // Output: 4
Run Code Online (Sandbox Code Playgroud)

我确信在C#中有一些正常的方法可以在运行时获取数据大小,但谷歌并没有提供太多帮助..这是我最后的希望

Luk*_*keH 24

Cory的回答之后,如果性能很重要并且你需要经常使用这段代码,那么你可以缓存大小,这样动态方法只需要为每种类型构建和执行一次:

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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Gro*_*kys 22

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

System.Runtime.InteropServices.Marshal.SizeOf(x)
Run Code Online (Sandbox Code Playgroud)

正如dtb所提到的,这个函数在编组后返回变量的大小,但根据我的经验,这通常是你想要的大小,就像在纯托管环境中一样,变量的大小没什么意义.

  • 不是真的......"Marshal.SizeOf"在编组*后返回大小*.例如,`Marshal.SizeOf('x')`返回1,而`sizeof(char)`返回2. (12认同)
  • 不是一个好的答案;尝试在 bool 上执行此操作,看看会得到什么。 (2认同)

Cᴏʀ*_*ᴏʀʏ 15

大小int总是32位.为什么需要在运行时获得大小?

说到这一点,你可以使用Marshal.SizeOf(),但这只是用于非托管代码.

偶然发现了一些显然会给你一个值类型大小的代码.它使用反射,与你想要使用的功能(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());
}
Run Code Online (Sandbox Code Playgroud)

  • 请记住,marshal.sizeof告诉你在编组方面的东西*的大小*不是*在管理方*占用多少内存*.这两个值可能非常不同. (6认同)

小智 5

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

byte[] dataBytes = BitConverter.GetBytes(x);
int dataLength= dataBytes.Length;
Run Code Online (Sandbox Code Playgroud)

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