C#内插字符串

前言

在.Net 6.0的时候,引入内插字符串,在 C# String.Format性能优化 ,也讲到了内插字符串,也对DefaultInterpolatedStringHandler进行了源码学习,这里为什么又为什么在说一次呢?
因为在.Net 8,BCL类库中还有一些地方在内插字符串进行代码的优化. 这个在项目中经常看到字符串拼接(+=), 所以平时在写代码的时候,对于简单的字符串拼接,不要直接在进行拼接了.

内插字符串,在这里的优点,就是减少临时字符串的产生,降低GC的压力,从而提高程序的性能.

不管是不是老项目(.Net Framework),还是.Net(.Net Core),在简单的字符串拼接时,都应尽量使用这种语法$"age={0}",这样如果是老项目迁移版本到.Net后,不需要修改代码,就可以提高性能.

看看这个issue: Use string interpolation in a few more places (#82096) .在.Net BCL基础库中更多的地方使用内插字符串.

c# 使用内插字符串的方式,来优化简单的字符串拼接

示例代码

public class StringInterpolated
{
	public string Test1()
	{
		int a = 20;
		return $"age={a}";  //这种方式就是内插字符串
	}

	public string Test2()
	{
		int a = 20;
		return string.Format("age={0}", a); //在字符串比较短的时候,可以使用,短字符串时,在栈上分配空间,大字符串的使用数组池
	}

	public string Test3()
	{
		int a = 20;
		return "age=" + a;  //不建议使用这种方式,进行字符串拼接
	}
}

使用DnSpy.exe查看编译后的代码

public class StringInterpolated
{
	// Token: 0x0600003F RID: 63 RVA: 0x00002A64 File Offset: 0x00000C64
	public string Test1()
	{
		int a = 20;
		DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(4, 1); //预分配字符串空间
		defaultInterpolatedStringHandler.AppendLiteral("age=");  //拼接常量字符串
		defaultInterpolatedStringHandler.AppendFormatted<int>(a); 
		return defaultInterpolatedStringHandler.ToStringAndClear(); //生成字符串
	}

	// Token: 0x06000040 RID: 64 RVA: 0x00002AA0 File Offset: 0x00000CA0
	public string Test2()
	{
		int a = 20;
		return string.Format("age={0}", a); //使用string.Format,这种方式也是可以的,在短字符串的时候,在栈上分配空间,在大字符串的时候,也会复用池化的数组
	}

	// Token: 0x06000041 RID: 65 RVA: 0x00002AC8 File Offset: 0x00000CC8
	public string Test3()
	{
		return "age=" + 20.ToString();
	}
}


秋风 2023-07-23