C#中高效将值类型写入字节数组指定偏移量的实现方案
嘿,我完全懂你想要的这种零额外内存分配的高效写法!针对你需求的「直接将值类型写入已有字节数组指定偏移、无额外内存分配」,这里有两种实用方案,适配不同场景:
高效无分配地将值类型写入字节数组指定偏移位置
方案1:Unsafe 指针写法(你思路的通用强化版)
你一开始的unsafe方向完全正确,这种写法是性能天花板级别的——全程零内存分配,直接操作数组内存。我们可以把它封装成支持任意值类型的通用方法:
public unsafe static void WriteValueToBytes<T>(T value, byte[] output, int byteIndex) where T : unmanaged { if (output == null) throw new ArgumentNullException(nameof(output)); if (byteIndex < 0 || byteIndex + sizeof(T) > output.Length) throw new ArgumentOutOfRangeException(nameof(byteIndex)); fixed (byte* bytePtr = output) { T* valuePtr = (T*)(bytePtr + byteIndex); *valuePtr = value; } }
使用示例:
// 初始化一个足够大的字节数组 byte[] buffer = new byte[16]; // 把double写入数组的第4个字节开始的位置(偏移量4) double pi = 3.1415926; WriteValueToBytes(pi, buffer, 4); // 把int写入数组起始位置 int number = 12345; WriteValueToBytes(number, buffer, 0);
这里的unmanaged约束确保T是纯值类型(无引用成员),完美适配你的需求,没有任何额外内存开销。
方案2:Span 安全无分配写法(推荐现代.NET环境)
如果你的项目禁用unsafe代码(比如遵循严格的安全规范),.NET Core 2.1+、.NET 5+提供的Span<T>是绝佳替代——它同样零分配,且完全类型安全,不需要unsafe关键字:
public static void WriteValueToBytes<T>(T value, byte[] output, int byteIndex) where T : unmanaged { if (output == null) throw new ArgumentNullException(nameof(output)); if (byteIndex < 0 || byteIndex + sizeof(T) > output.Length) throw new ArgumentOutOfRangeException(nameof(byteIndex)); Span<T> valueSpan = output.AsSpan(byteIndex).Slice(0, sizeof(T)).Cast<T>(); valueSpan[0] = value; }
使用方式和上面完全一致:
byte[] buffer = new byte[16]; float e = 2.718f; // 把float写入数组第8个字节位置 WriteValueToBytes(e, buffer, 8);
Span内部会安全地处理内存直接操作,既保留了零分配的高效性,又避免了unsafe代码的潜在风险,是现代.NET推荐的内存操作方式。
为什么这两种方案比BitConverter+BlockCopy更优?
- 彻底避免了
BitConverter.GetBytes每次调用都会分配新字节数组的开销 - 省去了
Buffer.BlockCopy的内存拷贝步骤,直接原地修改目标数组,性能更高效
不管你选哪种,都能完美满足你「无需分配新内存、直接写入指定偏移」的核心需求。
内容的提问来源于stack exchange,提问作者MAK
相关产品推荐
相关产品推荐

