.NET 5+ 推荐使用 Convert.FromHexString,它自动处理空格、校验偶数长度并拒绝非法字符;旧框架需手动清理前缀并逐字符校验合成字节数组。

用 Convert.FromHexString 最安全、最直接
这是 .NET 5+ 官方推荐的唯一标准方式,无需手动校验长度、大小写或前缀。它内部已处理所有边界情况,比如自动忽略空格、拒绝非法字符、强制偶数长度校验。
常见错误是仍用老式 Regex + int.Parse 或手写循环——既易出错又慢,还可能漏掉 "0x" 前缀处理逻辑。
-
Convert.FromHexString("A1B2")→byte[] { 0xA1, 0xB2 } -
Convert.FromHexString("a1 b2")→ 合法(支持空格分隔) -
Convert.FromHexString("A1B")→ 抛出ArgumentException(长度必须为偶数) - 不接受
"0xA1B2"这类带前缀的字符串,需先用.Replace("0x", "").Replace("0X", "")清理
兼容 .NET Framework 4.x 的 fallback 写法
若项目卡在旧框架,别用 BitConverter 或 int.Parse 分组——它们对奇数长度、非十六进制字符容忍度过高,容易静默失败或抛出意外异常。
推荐封装一个健壮的辅助方法,核心是逐字符校验 + 移位合成:
public static byte[] HexStringToBytes(string hex) {
if (string.IsNullOrWhiteSpace(hex)) throw new ArgumentException("hex cannot be null or empty");
hex = hex.Replace("0x", "").Replace("0X", "").Replace(" ", "");
if (hex.Length % 2 != 0) throw new ArgumentException("hex string must have even length");
var bytes = new byte[hex.Length / 2];
for (int i = 0; i < hex.Length; i += 2) {
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
}
return bytes;
}
- 必须显式剔除
"0x"和空格,Convert.ToByte(..., 16)不识别前缀 - 用
Substring比正则或char手动转更稳:避免大小写混淆('a'和'A'都合法) - 不要用
Encoding.UTF8.GetBytes()直接转——那是把字符 ASCII 码当字节,不是解析十六进制值
警惕 Encoding 类误用场景
很多初学者看到 “字符串转 byte[]” 就本能调用 Encoding.UTF8.GetBytes("A1B2"),结果得到的是 { 65, 49, 66, 50 }(即 'A','1','B','2' 的 ASCII 码),完全不是十六进制解析。
- 只要目标是“把十六进制表示的数值还原成原始字节”,就和文本编码无关
-
Encoding只适用于“把人类可读字符串按某种规则序列化为字节”,比如存文件、发 HTTP Body - 混淆这两者会导致加密/解密、协议解析、硬件通信等场景彻底失败,且错误不易察觉
性能与大字符串注意事项
Convert.FromHexString 在 .NET 6+ 已做 SIMD 优化,百万级字符也能毫秒级完成;但若需高频调用(如日志解析、实时协议包处理),仍要注意:
- 避免重复分配:对固定格式的 hex 字符串,可预编译正则或缓存清理逻辑(如用
Span<char></char>替代Substring) - 超长字符串(>1MB)建议分块解析,防止 GC 压力;
Convert.FromHexString本身不支持流式,需自行切片 - 若输入来源不可信(如用户上传、网络接收),务必加 try/catch —— 解析失败是常态,不是异常路径
真正难的从来不是“怎么写”,而是判断输入是否可信、失败后要不要丢弃整包、以及字节序是否隐含在 hex 表达中(比如某些协议里 "0001" 表示小端 256,而非字面值 1)。这些细节不会出现在函数文档里,得看协议规范。


















