【C#】C#性能优化:用StringBuilder与ToString("X2")提升字符串拼接与字节转换效率

一、使用 StringBuilder 代替 += 来优化字符串拼接

从代码的可读性性能维护性三个方面进行分析。以下是详细的分析:

实现 1

uint crc = CRC16(data, Convert.ToUInt32(data.Length));
string ds = "";
foreach (var messageByte in data)
{
    ds += messageByte.ToString("X2");
}
ds += (Convert.ToString(crc, 16).ToUpper().PadLeft(4, '0').Substring(2, 2) + 
       Convert.ToString(crc, 16).ToUpper().PadLeft(4, '0').Substring(0, 2));
byte[] sendData = null;
sendData = strToHexByte(ds.Trim());
SendData(sendData);

缺点:

  1. 性能问题
    • 使用了字符串拼接 (ds += ...),这会导致每次拼接都会创建新的字符串对象,增加内存分配和垃圾回收的压力。
    • 对于较大的数据量,这种方式的性能会显著下降。

改进方案

一个问题:频繁的字符串拼接。在 C# 中,频繁使用 += 拼接字符串会导致性能问题,因为字符串是不可变的,每次拼接都会创建一个新的字符串对象。

为了提高性能和代码的可读性,可以使用 StringBuilder 来优化字符串拼接。以下是改进后的代码:

uint crc = CRC16(data, Convert.ToUInt32(data.Length));
StringBuilder sb = new StringBuilder();

// 将每个字节转换为两位十六进制字符串
foreach (var messageByte in data)
{
    sb.Append(messageByte.ToString("X2"));
}

// 添加 CRC 校验值
string crcStr = crc.ToString("X4");
sb.Append(crcStr.Substring(2, 2)); // 高位
sb.Append(crcStr.Substring(0, 2)); // 低位

// 转换为字节数组并发送
byte[] sendData = strToHexByte(sb.ToString());
SendData(sendData);

改进后的优点:

  1. 性能提升

    • 使用 StringBuilder 避免了频繁的字符串拼接操作,显著提高了性能,尤其是在处理大量数据时。
  2. 代码清晰

    • 逻辑更加清晰,易于阅读和维护。
    • 避免了多余的空格处理和重复的 Convert.ToString 调用。
  3. 一致性

    • 所有字节和 CRC 校验值的格式化方式保持一致,减少了潜在的错误。

总结

  • 从性能和可维护性的角度来看,推荐使用改进后的 StringBuilder 实现,这是处理字符串拼接的最佳实践。

最终答案:改进后的 StringBuilder 实现更好

二、Byte.ToString("X2")Convert.ToString(Byte, 16).ToUpper().PadLeft(2, '0')

对于任何字节值(byte 类型),messageByte.ToString("X2")Convert.ToString(data[i], 16).ToUpper().PadLeft(2, '0') 的输出效果是一样的。它们都用于将一个字节(byte 类型)转换为两位的大写十六进制字符串。以下是详细的对比和分析:


1. messageByte.ToString("X2")

  • 作用

    • 将字节值直接格式化为两位大写的十六进制字符串。
    • "X2" 是标准的格式化字符串:
      • "X" 表示十六进制格式。
      • "2" 表示结果至少包含两位字符,不足时用前导零补齐。
  • 示例

    byte b = 15;
    string result = b.ToString("X2"); // 输出: "0F"
    
  • 特点

    • 简洁、直观。
    • 内置支持前导零填充,无需额外操作。

2. Convert.ToString(data[i], 16).ToUpper().PadLeft(2, '0')

  • 作用

    • Convert.ToString(data[i], 16):将字节值转换为小写的十六进制字符串(无前导零)。
    • .ToUpper():将小写字母转换为大写字母。
    • .PadLeft(2, '0'):确保字符串长度为 2,不足时在左侧填充 '0'
  • 示例

    byte b = 15;
    string result = Convert.ToString(b, 16).ToUpper().PadLeft(2, '0'); // 输出: "0F"
    
  • 特点

    • 更冗长,需要多个方法调用。
    • 需要手动处理大小写和前导零。

输出效果对比

对于任何字节值(byte 类型),两种方法的输出结果完全一致。例如:

字节值 ToString("X2") Convert.ToString(...)
0 "00" "00"
15 "0F" "0F"
255 "FF" "FF"

性能对比

虽然两种方法的输出相同,但在性能上存在一些差异:

  1. ToString("X2")

    • 更高效,因为它是专门设计用于格式化的内置方法。
    • 不需要额外的字符串操作(如 ToUpperPadLeft)。
  2. Convert.ToString(...)

    • 性能稍差,因为它涉及多个步骤(转换、大小写调整、填充)。
    • 每个步骤都会增加函数调用的开销。

推荐使用

如果目标是将字节值转换为两位大写的十六进制字符串,推荐使用 ToString("X2"),因为它更简洁、高效且易于阅读。

foreach (var messageByte in data)
{
    ds += messageByte.ToString("X2");
}

Convert.ToString(...) 的方式更适合在需要更灵活的转换场景下使用(例如,非固定长度的十六进制字符串)。

posted @   ban_boi  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示