固定缓冲区和使用' MarshalAs ' attr与' UnmanagedType.ByValArray '之间有什么
本文关键字:UnmanagedType ByValArray 之间 什么 attr MarshalAs 缓冲区 | 更新日期: 2023-09-27 18:15:37
好吧,有一些明显的区别:
固定缓冲区:
- 必须在不安全块中声明(这意味着整个项目必须使用
-unsafe
开关编译)。 - 使用固定缓冲区时,包含对象必须是固定的,
使用MarshalAs
属性:
- 虽然大小给了编组程序,但不能保证实际数组有足够的元素计数,也不能保证它不是null。
- 可以像其他数组一样简单直观地使用。
但是我找不到答案,为什么需要固定缓冲区?
什么时候必须使用它们?
假设可以验证常规托管数组的大小,为什么要使用它?
我可以想到性能约束,这可能会使一个选择固定的缓冲区而不是常规数组…
就这些吗?
是的,效率当然是主要原因。当你应用UnmanagedType.ByValArray
时,结构体必须总是被封送。换句话说,CLR被迫创建一个结构体的新副本,并用来自托管结构体的值初始化它,因为该结构体的非托管布局是不同的。当您使用固定缓冲区时,可以避免这种情况,前提是该结构体的其他成员也是可篡改的。在这种情况下,CLR可以简单地传递一个指向该结构体的指针。当然快多了。
这两种情况基本上都是无法验证的。如果本机代码写回结构体总是不安全的,当它写过数组的末尾时就会发生内存损坏。很难诊断。当您使用固定大小的缓冲区时,需要显式地使用不安全的关键字,这只适用于在c#代码中访问固定大小的缓冲区时缺乏索引检查。