字符串拼接问题的最佳解决方案

ZString:零分配的.NET Core和Unity字符串构建器

ZString
项目地址:https://gitcode.com/gh_mirrors/zs/ZString/?utm_source=artical_gitcode&index=top&type=card&webUrl&isLogin=1

在这里插入图片描述

此图表比较了以下代码:

  • “x:” + x + " y:" + y + " z:" + z
  • ZString.Concat(“x:”, x, " y:“, y, " z:”, z)
  • string.Format(“x:{0} y:{1} z:{2}”, x, y, z)
  • ZString.Format(“x:{0} y:{1} z:{2}”, x, y, z)
  • new StringBuilder(), Append(), .ToString()
  • ZString.CreateStringBuilder(), Append(), .ToString()

C#编译器会将"x:" + x + " y:" + y + " z:" + z转化为String.Concat(new[]{ “x:”, x.ToString(), " y:“, y.ToString(), " z:”, z.ToString() }),其中每个.ToString和参数数组都会产生分配。而string.Format调用String.Format(string, object, object, object)导致每个参数都要经历int到object的装箱。

所有ZString方法仅分配最终字符串。此外,ZString允许访问内部缓冲区,当输出目标具有无字符串API(如Unity TextMeshPro的SetCharArray)时,可以实现完全零分配。

Unity使用:

下载ZString.Unity.x.x.x.unitypackage,直接导入Unity

全部导入后也许你的项目中之前就存在这个文件
System.Runtime.CompilerServices.Unsafe
那么重复导入后会报错
一般来说删掉新导入的文件就行,跟之前的公用

ZString 使用了一些底层优化技术,比如Span 和内存池,这些都需要用到 System.Runtime.CompilerServices.Unsafe 来绕过一些 .NET 的安全限制以获得更高性能(比如直接操作内存)。很多 SDK(比如 AppsFlyer、Firebase、Addressables 等)都会附带它。

常用方式

using Cysharp.Text;
using UnityEngine;

public class ZStringTest : MonoBehaviour
{
    void Start()
    {
        ///--------------------Format----------------------
        // 基本使用
        string name = "Player";
        int score = 100;
        int x = 1;
        int y = 2;
        int z = 3;


        // 普通字符串拼接(GC 会产生垃圾)
        string s1 = "Name: " + name + ", Score: " + score;
        //也会有装箱操作
        string s = $"Name: {name}, Score: {score}";
        // ZString 拼接(无 GC)
        string s2 = ZString.Format("Name: {0}, Score: {1}", name, score);
        
        //输出:1,2,3
        Debug.Log(ZString.Join(',', x, y, z));
        
        //输出:123
        Debug.Log(ZString.Concat(x, y, z));
        
        //输出:Name: Player, Score: 100
        Debug.Log(s2);
        
        
        ///--------------------StringBuilder-----------------
        using (var sb = ZString.CreateStringBuilder())
        {
            sb.Append("This is ");
            sb.Append(2025);
            sb.Append(" test.");
            string result = sb.ToString(); // 一次性生成
            //输出:This is 2025 test.
            Debug.Log(result);
        } // 自动释放内存池
        
        ///--------------------TextMeshPro-----------------
         
        // 在Unity中,直接写入TextMeshPro,避免完全分配字符串
        tmp.SetTextFormat("Position: {0}, {1}, {2}", x, y, z);

       // 准备格式,返回值应存储在字段(如RegexOptions.Compile)
       var prepared = ZString.PrepareUtf16<int, int>("x:{0}, y:{1:000}");
       _ = prepared.Format(10, 20);

       // C# 8.0,使用声明
       // 创建Utf8 StringBuilder,直接构建Utf8以避免编码
       using var sb2 = ZString.CreateUtf8StringBuilder();

       sb2.AppendFormat("foo:{0} bar:{1}", x, y);

       // 直接写入流或dest来避免分配
       await sb2.WriteToAsync(stream);
       sb2.CopyTo(bufferWritter);
       sb2.TryCopyTo(dest, out var written);
    }
}
posted @ 2025-04-21 14:00  游戏开发李万兴  阅读(69)  评论(0)    收藏  举报  来源