You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取ReadOnlySpan这类ref struct的托管内存大小?

如何检查ref struct(如ReadOnlySpan)的内存大小?

你提到的问题很典型——ref struct(比如ReadOnlySpan<byte>)因为其特殊的设计(仅能在栈上分配、无法被装箱),常规的内存大小检查方法都会失效,我们来一步步拆解原因并给出可行方案:

为什么常规方法行不通?

你尝试的几种方法都因为ref struct的特性被编译器阻止:

  • unsafe { size = sizeof(ReadOnlySpan<byte>); } 报CS0208:编译器禁止对ref struct直接使用sizeof,这类类型虽属值类型,但受限于栈分配约束,不允许在unsafe块中直接获取其大小。
  • Marshal.SizeOf(default(ReadOnlySpan<byte>)) 和 Marshal.SizeOf(typeof(ReadOnlySpan<byte>)) 报错:Marshal.SizeOf仅适用于可 blittable 的非托管类型或能转换为非托管类型的类型,而ref struct无法被装箱或转换为非托管类型,自然不支持。

可行的解决方案:使用Unsafe.SizeOf<T>()

最简单可靠的方法是使用System.Runtime.CompilerServices.Unsafe类中的SizeOf<T>()方法,它可以直接获取任意值类型(包括ref struct)的内存大小——原理是直接读取类型的元数据布局信息,不需要实例,也不受装箱或托管类型限制。

示例代码:

using System.Runtime.CompilerServices;

// 获取ReadOnlySpan<byte>的内存大小
int spanSize = Unsafe.SizeOf<ReadOnlySpan<byte>>();
// 64位系统下返回16(两个8字节的IntPtr字段),32位系统下返回8(两个4字节的IntPtr字段)

注意:不要手动计算ref struct的大小(比如假设ReadOnlySpan是两个IntPtr字段),因为类型的内部布局可能随.NET版本或平台变化,Unsafe.SizeOf<T>()会自动读取官方元数据,是最可靠的方式。

结合微软的in修饰符建议

回到你提到的微软《编写安全高效的C#代码》中的建议:对大小超过System.IntPtr.Size的readonly struct参数使用in修饰符。对于ReadOnlySpan<byte>这类ref struct,它的大小在64位系统下是16字节(超过8字节的IntPtr.Size),所以如果它作为参数传递时,使用in修饰符可以避免不必要的栈拷贝,进一步提升性能——不过要注意,ref struct本身已经是栈分配的,但in修饰符会确保参数是只读引用传递,优化效果更显著。

如果是你自定义的readonly ref struct,也可以用同样的方法检查大小,来决定是否使用in修饰符。

内容的提问来源于stack exchange,提问作者Joel V. Earnest-DeYoung

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.07 10:57:39