Split long interpolated string
一个例子:
1 2 3 4 5 6 | var a = $"Some value 1: {b1:0.00} Some value 2: {b2} Some value 3: {b3:0.00000} Some value 4: {b4:0.00} Some value 5: {b6:0.0} Some value 7: {b7:0.000000000}"; |
这有点难读。
我能做到
1 2 3 4 5 6 7 8 9 10 11 | var a = $"Some value 1: {b1:0.00} " + $"Some value 2: {b2} " + $"Some value 3: {b3:0.00000} " + $"Some value 4: {b4:0.00} " + $"Some value 5: {b6:0.0} " + $"Some value 7: {b7:0.000000000}"; |
但这里有一条评论说,这将是对
问题:可以吗?拆分长内插字符串还有哪些其他选项?
what this will be multiple calls to string.Format and I think it will
你说得对。你没有说你为什么在乎。为什么要避免?
is it ok to do?
我没事。
What are other options to split long interpolated string?
我将使用逐字插入字符串。那会很好地解决你的问题。
见
如何使用带插值的逐字字符串?
(因为这是你在问题中提到的链接,所以我不完全清楚你为什么问这个问题,因为你已经阅读了一个建议好答案的页面。)
I don't like $@ idea, it makes it worse than long string
你可能早点说过。
can't it be accidentally damaged by reformatting sources?
所有代码都可以通过更改源代码来更改。
What are other options to split long interpolated string?
一开始不要插补。使字符串成为资源,使类负责获取格式化的资源字符串,并隐藏如何在类的方法中格式化字符串的实现细节。
编译器做什么?好的。
从这里开始:好的。
1 2 3 4 5 6 7 8 9 10 11 | var a = $"Some value 1: {b1:0.00} " + $"Some value 2: {b2} " + $"Some value 3: {b3:0.00000} " + $"Some value 4: {b4:0.00} " + $"Some value 5: {b6:0.0} " + $"Some value 7: {b7:0.000000000}"; |
IL is a black box for me yet
Ok.
为什么不直接打开它呢?使用像ilspy、reflector等工具很容易。好的。
在代码中会发生的事情是,每一行都被编译成一个
更详细地说,
从所有这些可以推断,编译器很容易对其进行优化:如果我们有一个像
注意,字符串是.NET中的对象,但它们是"特殊的"。你可以从有一个特殊的
1 2 | var str ="foo" +"bar"; Console.WriteLine(str); |
在IL(当然是释放模式)中,这将给出:好的。
1 | L_0000: ldstr"foobar" |
tl;dr:所以,不管插入字符串的连接是否已经实现(它们没有实现),我都非常有信心编译器最终会处理这种情况。好的。
JIT是做什么的?好的。
下一个问题是:使用字符串的JIT编译器有多聪明?好的。
那么,让我们考虑一下,我们将教编译器有关
1 2 3 4 5 | var str =""; for (int i=0; i<10; ++i) { str +="foo"; } Console.WriteLine(str); |
编译器将简单地编译到IL的串联,这意味着IL将拥有一个非常直接的实现。在这种情况下,展开循环可以为程序的(运行时)性能带来很多好处:它可以简单地展开循环,将字符串追加10次,从而得到一个简单的常量。好的。
但是,将这些知识提供给JIT编译器会使其更加复杂,这意味着运行时将在JIT编译(计算出优化)上花费更多时间,执行(运行发出的汇编程序)的时间更少。剩下的问题是:会发生什么?好的。
启动程序,在写行上放置一个断点,然后点击ctrl-alt-d并查看汇编程序。好的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 00007FFCC8044413 jmp 00007FFCC804443F { str +="foo"; 00007FFCC8044415 mov rdx,2BEE2093610h 00007FFCC804441F mov rdx,qword ptr [rdx] 00007FFCC8044422 mov rcx,qword ptr [rbp-18h] 00007FFCC8044426 call 00007FFD26434CC0 [...] 00007FFCC804443A inc eax 00007FFCC804443C mov dword ptr [rbp-0Ch],eax 00007FFCC804443F mov ecx,dword ptr [rbp-0Ch] 00007FFCC8044442 cmp ecx,0Ah 00007FFCC8044445 jl 00007FFCC8044415 |
tl;dr:不,这没有优化。好的。
但我也希望JIT优化这一点!好的。
是的,嗯,我不太确定我是否同意这个观点。在运行时性能和JIT编译所花费的时间之间有一个平衡。注意,如果你这样做的话,我会认为你是在自找麻烦。另一方面,如果这是一个常见且微不足道的情况(比如连接的常量),那么优化就非常容易,并且不会影响运行时。好的。
换句话说:可以说,您不希望JIT对此进行优化,前提是这将花费太多时间。我相信我们可以信任微软明智地做出这个决定。好的。
另外,您应该认识到.NET中的字符串是高度优化的。我们都知道他们被大量使用,微软也是如此。如果你不是在写"非常愚蠢的代码",那么这是一个非常合理的假设,即它的性能会很好(除非得到证明)。好的。
选择?好的。
What are other options to split long interpolated string?
Ok.
使用资源。资源是处理多种语言的有用工具。如果这只是一个小的,非专业的项目,我根本就不会麻烦。好的。
或者,可以使用常量字符串连接的事实:好的。
1 2 3 4 5 6 7 8 9 10 11 12 13 | var fmt ="Some value 1: {1:0.00} " + "Some value 2: {2} " + "Some value 3: {3:0.00000} " + "Some value 4: {4:0.00} " + "Some value 5: {6:0.0} " + "Some value 7: {7:0.000000000}"; var a = string.Format(fmt, b1, b2, b3, b4, b5, b6, b7); |
好啊。