字符串是我们平时使用最多的一个类型,从C#6开始就支持插值字符串,方便我们进行字符串的操作,并且大部分分析器也推荐使用插值这种写法,因为它够使得我们的代码更加清晰简洁,到了.NET6中的C#10则为我们提供了更好的实现方式以及更佳的性能。 那么什么是插值字符串呢?它是以$符开头的,类似于 $"Hello {name}" 这样的字符串,下面的例子是插值字符串的简单使用:
var name = "插值字符串";
var hello = $"你好 {name}!";
var num= 10;
var numMessage= $"我喜欢数字 {num}";
我们不需要使用format就可以直接简化字符串拼接,并且对于一些简单的字符串拼接可以简化成``string.Concat
``,在.NET6之前的版本中它会被翻译成低版本C#中的string.Format形式,上述代码翻译成低版本C# 代码如下所示:
string name = "插值字符串";
string hello = string.Concat("你好 ", name, "!");
int num= 10;
string numMessage= string.Format("我喜欢数字 {0}", );
对于string.Format来说,如果参数是值类型会发生装箱,变为 object,这一点我们可以通过IL代码看出。这里需要注意的是插值字符串格式化的时候会使用当前的CultureInfo,如果我们需要使用不同的CultureInfo或手动指定CultureInfo,那么可以使用FormattableString或FormattableStringFactory来实现。代码如下会根据指定的CultureInfo显示出不同的数字格式:
var id=35000;
FormattableString str1 = $"id是{id}";
Console.WriteLine(str1.Format);
Console.WriteLine(str1.ToString(new CultureInfo("zh-CN")));
str1 = FormattableStringFactory.Create("Hello {0}", id);
Console.WriteLine(str1.Format);
Console.WriteLine(str1.ToString(new CultureInfo("en-US")));
在.NET6 中本文的第一段代码会翻译成生成下面这样的:
string name = "插值字符串";
string hello = string.Concat ("Hello ", name, "!");
int num= 10;
DefaultInterpolatedStringHandler defaultInterpolatedStringHandler = new DefaultInterpolatedStringHandler(11, 1);
defaultInterpolatedStringHandler.AppendLiteral("我喜欢数字 ");
defaultInterpolatedStringHandler.AppendFormatted(num);
string numDesc = defaultInterpolatedStringHandler.ToStringAndClear();
在.NET6中会由DefaultInterpolatedStringHandler处理插值字符串。它DefaultInterpolatedStringHandler是结构体,并且包含泛型方法AppendFormatted来避免装箱操作,这样它在format的时候性能更好。并且在.NET6中String增加了两个方法来支持使用新的插值处理方式,新增的方法代码如下所示:
/// Creates a new string by using the specified provider to control the formatting of the specified interpolated string.
/// An object that supplies culture-specific formatting information.
/// The interpolated string.
/// The string that results for formatting the interpolated string using the specified format provider.
public static string Create(IFormatProvider? provider, [InterpolatedStringHandlerArgument("provider")] ref DefaultInterpolatedStringHandler handler) => handler.ToStringAndClear();
/// Creates a new string by using the specified provider to control the formatting of the specified interpolated string.
/// An object that supplies culture-specific formatting information.
/// The initial buffer that may be used as temporary space as part of the formatting operation. The contents of this buffer may be overwritten.
/// The interpolated string.
/// The string that results for formatting the interpolated string using the specified format provider.
public static string Create(IFormatProvider? provider, Span initialBuffer, [InterpolatedStringHandlerArgument("provider", "initialBuffer")] ref DefaultInterpolatedStringHandler handler) => handler.ToStringAndClear();
下面我们来实现一个简单的插值字符串处理器,实现一个最基本的插值字符串处理器需要满足以下四个条件:
- 构造函数至少需要两个int参数,一个是字符串中常量字符的长度,一个是需要格式化的参数的数量;
- 需要具有public的AppendLiteral(string s)方法处理常量字符的拼接;
- 需要具有public的AppendFormatted(T t)方法处理参数;
- 自定义处理器需要使用InterpolatedStringHandler标记,并且处理器可以是class也可以是struct。下面的代码就实现了一个简单的插值字符串处理器
[InterpolatedStringHandler]
public struct CustomInterpolatedStringHandler
{
private readonly StringBuilder builder;
public CustomInterpolatedStringHandler(int literalLength, int formattedCount)
{
builder = new StringBuilder(literalLength);
}
public void AppendLiteral(string s)
{
builder.Append(s);
}
public void AppendFormatted(T t)
{
builder.Append(t?.ToString());
}
public override string ToString()
{
return builder.ToString();
}
}
当我们使用它的时候,可以这么用:
private static void LogInterpolatedString(string str)
{
Console.WriteLine(nameof(LogInterpolatedString));
Console.WriteLine(str);
}
private static void LogInterpolatedString(CustomInterpolatedStringHandler stringHandler)
{
Console.WriteLine(nameof(LogInterpolatedString));
Console.WriteLine(nameof(CustomInterpolatedStringHandler));
Console.WriteLine(stringHandler.ToString());
}
LogInterpolatedString("我喜欢的数字是10");
int num=20;
LogInterpolatedString($"我喜欢的数字是{num}");
输出结果如下:
LogInterpolatedString
我喜欢的数字是10
LogInterpolatedString
CustomInterpolatedStringHandler
我喜欢的数字是20
我们还可以在自定义的插值字符串处理器的构造器中增加自定义参数,使用InterpolatedStringHandlerArgument来引入更多构造器参数。我们改造一下上面CustomInterpolatedStringHandler代码:
[InterpolatedStringHandler]
public struct CustomInterpolatedStringHandler
{
private readonly StringBuilder builder;
private readonly int _limit;
public CustomInterpolatedStringHandler(int literalLength, int formattedCount) : this(literalLength, formattedCount, 0)
{ }
public CustomInterpolatedStringHandler(int literalLength, int formattedCount, int limit)
{
builder = new StringBuilder(literalLength);
_limit = limit;
}
public void AppendLiteral(string s)
{
builder.Append(s);
}
public void AppendFormatted(T t)
{
if (t is int n && n
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/125210.html
相关文章
-
Flutter — 加快开发速度的 IDE 快捷操作#yyds干货盘点#
摘要:夏天加快开发速度的快捷操作干货盘点快捷方式你可以用做更多神奇的事情选项返回这是您在中加快开发速度的魔杖。加快开发速度的快捷操作干货盘点选项卡不喜欢小部件用魔术棒取下它。 Flutter — 加快开发速度的 IDE 快捷方式上一个关于vscode 的插件推荐大家看的过瘾不,今天继续给大家带来一些关于android s...
-
#yyds干货盘点#——if条件优化
摘要:避免过长微软雅黑如果判断值满足多个条件,我们可能会这么写微软雅黑当条件太多时会变得很长,可读性很差,可以这样写 1.避免if过长如果判断值满足多个条件,我们可能会这么写:if (value === a || value === b || value === c) { ... }当条件太多时会变得很长,可读性很差,可以这样...
-
flutter 中的列表的性能优化续集#yyds干货盘点#
重新构建嵌套列表这一节使用 Slivers 而不是 ListViews 重建相同的 UI。前奏在这里https://blog.51cto.com/jianguo/4653002使用 Slivers 的列表列表下面的代码构建了与之前相同的 UI,但这次它使用Slivers 而不是收缩包装ListView对象。本页的其余部分将引导您逐步完成更改。如何将嵌套列表迁移到 Slive...
-
flutter 中的列表的性能优化前奏#yyds干货盘点#
摘要:只有内部列表需要设置。中的列表的性能优化前奏干货盘点而且你滑动的快的时候列表会抖动重新构建嵌套列表要了解如何使您的用户免受卡顿威胁,请等待我的第二节,下一节将使用而不是重建相同的。 这里是坚果前端小课堂,大家喜欢的话,可以关注我的公众号坚果前端,,或者加我好友,获取更多精彩内容嵌套列表 - ShrinkWrap 与 Sli...
-
#yyds干货盘点# 性能测试
摘要:下面就性能测试的概念分类等知识点进行总结学习。综合数据量测试指和压力性能测试负载性能测试疲劳性能测试相结合的综合测试。 性能测试无论是在考试还是工作中,都是一个经常出现的话题,性能测试有助于确认被测系统是否能够支持性能需求,以及预期的负载增长等。性能测试不只是关注不同负载场景下的响应时间等指标,它也要通过测试来发现在不同负载场景下会出现的,例如速度变慢、内存泄漏等问题的原因。下面就...
发表评论
0条评论
不知名网友
男|高级讲师
TA的文章
阅读更多Oracle数据库4031故障分析
阅读 3310·2023-01-11 11:02
Oceanbase新版本复合分区添加分区操作
阅读 3884·2023-01-11 11:02
VRRP高可用
阅读 2717·2023-01-11 11:02
Docker技术之构建镜像和网络模式解析
阅读 4894·2023-01-11 11:02
CISCO 4500 主引擎版故障处理
阅读 4400·2023-01-11 11:02
大数据开发系列五:kafka& zookeeper 配置kerberos认证
阅读 5109·2023-01-11 11:02
自研实时计算模块介绍及运维数据应用场景实施
阅读 4889·2023-01-11 11:02
DataX的限速与调优
阅读 3367·2023-01-11 11:02