C#:在运行时获取值类型变量的大小?
我知道 C 和 C++ 等语言允许在运行时使用 sizeof() 函数确定数据的大小(结构、数组、变量...)。我在 C# 中尝试过,显然它不允许将变量放入 sizeof() 函数中,但仅限类型定义(float、byte、Int32、uint 等...),我该怎么做?
实际上,我希望这种情况发生:
int x;
Console.WriteLine(sizeof(x)); // Output: 4
而不是:
Console.WriteLine(sizeof(int)); // Output: 4
我确信有一些正常的方法可以在 C# 中运行时获取数据的大小,但谷歌没有提供太多帮助..这是我最后的希望
I know languages such as C and C++ allow determining the size of data (structs, arrays, variables...) at runtime using sizeof() function. I tried that in C# and apparently it does not allow putting variables into the sizeof() function, but type defintions only (float, byte, Int32, uint, etc...), how am I supposed to do that?
Practically, I want this to happen:
int x;
Console.WriteLine(sizeof(x)); // Output: 4
AND NOT:
Console.WriteLine(sizeof(int)); // Output: 4
I'm sure there's some normal way to get the size of data at runtime in C#, yet google didn't give much help.. Here it is my last hope
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
继 Cory 的回答,如果性能很重要并且您需要经常使用此代码,那么您可以缓存大小,以便每个类型只需要构建和执行一次动态方法:
Following on from Cory's answer, if performance is important and you need to hit this code a lot then you could cache the size so that the dynamic method only needs to be built and executed once per type:
要在运行时查找任意变量
x
的大小,您可以使用 Marshal.SizeOf:正如 dtb 所提到的,该函数返回编组后变量的大小,但根据我的经验,这通常是您想要的大小,如纯托管环境中变量的大小没有什么意义。
To find the size of an arbitrary variable,
x
, at runtime you can use Marshal.SizeOf:As mentioned by dtb, this function returns the size of the variable after marshalling, but in my experience that is usually the size you want, as in a pure managed environment the size of a variable is of little interest.
int
的大小始终为 32 位。为什么需要在运行时获取大小?话虽如此,您可以使用
Marshal.SizeOf()
,但这实际上仅适用于非托管代码。我偶然发现了一些代码显然会给你一个值类型的大小。它使用反射,与您想要使用的功能 (
sizeof()
) 相比,这是一个相当昂贵的方法调用:The size of
int
is always going to be 32 bits. Why would you need to get the size at runtime?With that said, you could use
Marshal.SizeOf()
, but that's really intended for unmanaged code only.I stumbled upon some code that apparently will give you the size of a value type. It uses reflection and would be quite an expensive method call compared to the functionality you wanted to use (
sizeof()
):如果您正在执行诸如构建数据包以发送到设备之类的操作,请尝试以下操作:
例如,现在您可以将 dataBytes 数组复制到 dataPacket 数组的 Payload 部分,dataLength 会告诉您要复制多少字节,并且让您验证或设置数据包中的 PayloadLength 值。
If you are doing something like building data packets to send to a device, try this:
Now you can, for example, copy the dataBytes array to the Payload section of the dataPacket array, and dataLength will tell you how many bytes to copy, and let you validate or set the PayloadLength value in your data packet.
我想说的是使用类型推断来满足您的要求(“如果您将 x 的类型从 int 更改为 long long,则不必将每次出现的 sizeof(int) 替换为 sizeof(long long)”) :
但你不能这样做,因为 T 可能是一个“托管类型”——它可能是一个带有对象引用字段的结构。似乎没有办法将 T 限制为仅非托管类型。
您可以使用静态帮助器类:
I was going to say use type inference to meet your requirement ("if you change the type of x from int to say long long, you don't have to replace every occurrence of sizeof(int) with sizeof(long long)"):
But you can't do that, because T might be a "managed type" -- it might be a struct with an object reference field. There doesn't seem to be a way to constrain T to only unmanaged types.
You could use a static helper class:
继续在 CORY 发布的代码中添加一些安全/性能/便利功能,对于不那么偏执的 LukeH 的代码应该足够了。
简而言之,此类返回类型大小,确保尽可能使用缓存,并包装来自外部类的异常。
您可能想要重写包罗万象的块以更好地适合您的项目。
Went ahead and added some safety/performance/convenience features to the code CORY posted, for the less paranoid LukeH's code should suffice.
In short this class returns type sizes, ensuring a cache is used whenever possible, wrapping up exceptions from external classes as it goes.
You may want to rewrite the catch-all blocks to better suit your project.
从
netcore1.0
开始,有System.Runtime.CompilerServices.Unsafe.SizeOf
方法,为您提供任何对象的大小。方法是在运行时实现的,所以它应该非常快。注意:似乎该方法返回引用类型的指针大小(
sizeof(IntPtr)
)而不是实际大小用法:
Starting with
netcore1.0
there isSystem.Runtime.CompilerServices.Unsafe.SizeOf
method that gives you size of any object. Method is implemented in the runtime so it should be very fast.Note: seems that method returns pointer size (
sizeof(IntPtr)
) for reference type instead of actual sizeUsage: