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

如何在C#中绕过校验创建无效decimal值以模拟C库返回结果?

解决方法:强行创建指定字节的无效decimal

背景

你在调用C库时,必须传入decimal类型让C函数填充字节(存储日期时间数字字符的字节数组),但该decimal并非有效值。现在需要Mock这个委托,需要绕过decimal的有效性校验,直接写入指定字节。

方法1:使用unsafe代码直接操作内存

通过unsafe代码固定decimal变量的内存地址,将目标字节数组直接复制到该内存区域,绕过构造函数的校验。

首先确保项目已启用允许不安全代码(在项目属性→生成→勾选“允许不安全代码”)。

示例代码:

// 模拟C函数返回的字节数组:对应字符串"2001020304050678"的ASCII字节
byte[] targetBytes = System.Text.Encoding.ASCII.GetBytes("2001020304050678");
// 初始化decimal变量
decimal dummyDecimal = 0M;

unsafe
{
    fixed (byte* decimalPtr = &System.BitConverter.GetBytes(dummyDecimal)[0])
    {
        // 将目标字节复制到decimal的内存中(decimal占16字节,这里只覆盖前16个字节)
        for (int i = 0; i < targetBytes.Length && i < 16; i++)
        {
            *(decimalPtr + i) = targetBytes[i];
        }
    }
}

// 此时dummyDecimal已被填充指定字节,可用于Mock委托调用

方法2:使用Marshal类操作非托管内存

通过非托管内存中转,将字节数组写入内存后转换为decimal,无需启用unsafe代码。

示例代码:

// 模拟C函数返回的字节数组
byte[] targetBytes = System.Text.Encoding.ASCII.GetBytes("2001020304050678");
// 分配非托管内存(decimal占16字节)
IntPtr unmanagedPtr = System.Runtime.InteropServices.Marshal.AllocHGlobal(16);

try
{
    // 将字节数组复制到非托管内存
    System.Runtime.InteropServices.Marshal.Copy(targetBytes, 0, unmanagedPtr, targetBytes.Length);
    // 将非托管内存转换为decimal
    decimal mockDecimal = (decimal)System.Runtime.InteropServices.Marshal.PtrToStructure(unmanagedPtr, typeof(decimal));
    
    // 使用mockDecimal进行委托Mock
}
finally
{
    // 释放非托管内存
    System.Runtime.InteropServices.Marshal.FreeHGlobal(unmanagedPtr);
}

注意事项

  • 这两种方法创建的decimal是无效的,仅能用于内存字节读取,不能进行任何算术运算或格式化操作,否则会抛出异常。
  • 确保目标字节数组长度不超过16字节(decimal的固定大小),超出部分会被忽略。

内容的提问来源于stack exchange,提问作者Helena

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 16:14:57