当前位置: 首页 > article >正文

C#常考随笔2:函数中多次使用string的+=处理,为什么会产生大量内存垃圾(垃圾碎片),有什么好的方法可以解决?

在 C# 中,由于string类型是不可变的,当在函数中多次使用+=操作符来拼接字符串时,每次操作都会创建一个新的string对象,旧的对象则成为垃圾对象,这会导致大量的内存分配和垃圾回收,产生内存垃圾和碎片。

在需要多次拼接字符串的场景中,优先使用StringBuilder类,并根据情况预分配容量,或者使用string.Join方法,减少内存垃圾的产生。

1. 使用StringBuilder

StringBuilder类是一个可变的字符串类型,它内部维护了一个字符数组,当需要追加字符串时,会在这个数组上进行操作,而不是像string那样每次都创建新的对象。因此,使用StringBuilder可以显著减少内存分配和垃圾回收的开销。

示例代码

using System;
using System.Text;

class Program
{
    static void Main()
    {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < 1000; i++)
        {
            sb.Append(i.ToString());
        }
        string result = sb.ToString();
        Console.WriteLine(result);
    }
}

2. 预分配StringBuilder的容量

在创建StringBuilder对象时,可以预先指定其容量,这样可以避免在追加字符串时频繁地进行数组扩容操作,进一步提高性能。

示例代码

using System;
using System.Text;

class Program
{
    static void Main()
    {
        // 假设最终字符串长度大约为 5000
        StringBuilder sb = new StringBuilder(5000); 
        for (int i = 0; i < 1000; i++)
        {
            sb.Append(i.ToString());
        }
        string result = sb.ToString();
        Console.WriteLine(result);
    }
}

3. 使用string.Join方法

如果需要将一个字符串数组或集合中的元素拼接成一个字符串,可以使用string.Join方法。string.Join方法会根据元素的数量和长度预先计算所需的内存空间,然后一次性分配,避免了多次创建string对象。

示例代码

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        List<string> stringList = new List<string>();
        for (int i = 0; i < 1000; i++)
        {
            stringList.Add(i.ToString());
        }
        string result = string.Join("", stringList);
        Console.WriteLine(result);
    }
}

http://www.kler.cn/a/520578.html

相关文章:

  • 【架构面试】一、架构设计认知
  • 认知计算与 AI 大模型:数据仓库、数据湖与数据分析的变革力量
  • Spring集成Redis|通用Redis工具类
  • 嵌入式蓝桥杯电子赛嵌入式(第14届国赛真题)总结
  • 「 机器人 」系统辨识实验浅谈
  • Spring Boot整合JavaMail实现邮件发送
  • SocketCAN
  • WebSocket 心跳机制:确保连接稳定与实时性
  • 【Rust自学】15.5. Rc<T>:引用计数智能指针与共享所有权
  • ubuntu 更新24LTS中断导致“系统出错且无法恢复,请联系系统管理员”
  • 【MySQL】--- 复合查询 内外连接
  • 使用scikit-learn中的KNN包实现对鸢尾花数据集或者自定义数据集的的预测
  • oracle 分区表介绍
  • [特殊字符]【计算机视觉】r=2 采样滤波器全解析 ✨
  • leetcode_链表 876.链表的中间节点
  • 利用Redis实现数据缓存
  • docker安装MySQL8:docker离线安装MySQL、docker在线安装MySQL、MySQL镜像下载、MySQL配置、MySQL命令
  • PHP反序列化练习
  • Semantic Kernel - Kernel理解
  • 719.找出第K小的数对距离(双指针、K值问题)
  • On to OpenGL and 3D computer graphics
  • 【C++高并发服务器WebServer】-8:终端、进程组、会话、守护进程
  • git回退
  • 家居 EDI:Haverty‘s EDI 需求分析
  • 【Postman接口测试】Postman的常见断言
  • 【数据结构】空间复杂度