嗯,有一些明显的区别:
固定缓冲区:
-unsafe
开关编译)。使用MarshalAs
属性:
但是我找不到答案,为什么首先需要固定缓冲区呢? 什么时候必须使用它们? 为什么人们会想要使用它,假设一个人可以验证常规托管数组的大小?
我可以想到性能限制,可能会让人选择固定缓冲区而不是常规数组... 这就是全部?
提前致谢。
答案 0 :(得分:4)
是的,效率肯定是主要原因。当您应用UnmanagedType.ByValArray
时,结构必须始终被封送。换句话说,CLR被强制创建结构的新副本,并使用来自托管结构的值对其进行初始化,因为结构的非托管布局是不同的。当您使用固定缓冲区时,可以避免这种情况,前提是结构的其他成员也是blittable。在这种情况下,CLR可以简单地传递指向结构的指针。当然快得多。
有一些互操作方案,必须使用固定大小的缓冲区。通常,当阵列成员未对齐时,这违反了.NET内存模型的原子性保证。或者声明一个union(字段彼此重叠)和CLR对象,以防止引用类型的字段与值类型的字段重叠。这与垃圾收集器不兼容,它无法可靠地检测到对象指针。在这种情况下,你会在运行时得到一个TypeLoadException。
这两种情况都是根本无法验证的。如果本机代码写回结构,则总是不安全的,当它写入数组末尾时会发生内存损坏。非常难以诊断。当您使用固定大小缓冲区时,显式使用 unsafe 关键字的需要仅适用于在C#代码中访问固定大小缓冲区时缺少索引检查。