String Interpolation vs String.Format

时间:2015-09-01 23:26:11

标签: c# string performance resharper string-interpolation

使用字符串插值之间是否存在明显的性能差异:

myString += $"{x:x2}";

vs String.Format()?

myString += String.Format("{0:x2}", x);

我只是问,因为Resharper正在提示修复,我之前被愚弄了。

4 个答案:

答案 0 :(得分:58)

值得注意的是相对的。但是:字符串插值在编译时变为string.Format(),因此它们应该以相同的结果结束。

但是有一些细微的差别:正如我们可以从this问题中看出的那样,格式说明符中的字符串连接会导致额外的string.Concat()调用。

答案 1 :(得分:5)

答案是是和不是。 ReSharper 愚弄了您,因为没有显示出性能最高的 third 变体。列出的两个变体产生相等的IL代码,但是以下内容确实可以增强:

myString += $"{x.ToString("x2")}";

完整测试代码

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Diagnosers;
using BenchmarkDotNet.Diagnostics.Windows;
using BenchmarkDotNet.Running;

namespace StringFormatPerformanceTest
{
    [Config(typeof(Config))]
    public class StringTests
    {
        private class Config : ManualConfig
        {
            public Config() => AddDiagnoser(MemoryDiagnoser.Default, new EtwProfiler());
        }

        [Params(42, 1337)]
        public int Data;

        [Benchmark] public string Format() => string.Format("{0:x2}", Data);
        [Benchmark] public string Interpolate() => $"{Data:x2}";
        [Benchmark] public string InterpolateExplicit() => $"{Data.ToString("x2")}";
    }

    class Program
    {
        static void Main(string[] args)
        {
            var summary = BenchmarkRunner.Run<StringTests>();
        }
    }
}

测试结果

|              Method | Data |      Mean |  Gen 0 | Allocated |
|-------------------- |----- |----------:|-------:|----------:|
|              Format |   42 | 118.03 ns | 0.0178 |      56 B |
|         Interpolate |   42 | 118.36 ns | 0.0178 |      56 B |
| InterpolateExplicit |   42 |  37.01 ns | 0.0102 |      32 B |
|              Format | 1337 | 117.46 ns | 0.0176 |      56 B |
|         Interpolate | 1337 | 113.86 ns | 0.0178 |      56 B |
| InterpolateExplicit | 1337 |  38.73 ns | 0.0102 |      32 B |

InterpolateExplicit()方法更快,因为我们现在明确告诉编译器使用string。无需box要格式化的对象。拳击确实非常昂贵。另外,请注意,我们稍微减少了分配。

答案 2 :(得分:3)

字符串插值在编译时变为string.Format()。

同样在string.Format中,您可以为单个参数指定多个输出,为单个参数指定不同的输出格式。但我认为字符串插值更具可读性。所以,这取决于你。

a = string.Format("Due date is {0:M/d/yy} at {0:h:mm}", someComplexObject.someObject.someProperty);

b = $"Due date is {someComplexObject.someObject.someProperty:M/d/yy} at {someComplexObject.someObject.someProperty:h:mm}";

有一些效果测试结果https://koukia.ca/string-interpolation-vs-string-format-string-concat-and-string-builder-performance-benchmarks-c1dad38032a

答案 3 :(得分:3)

问题是关于性能的,但是标题只是说“ vs”,所以我想不得不再增加一些要点,尽管其中有些是有根据的。

  • 本地化

    • 字符串内插由于其内联代码性质而无法本地化。在本地化之前,它已变成string.Format。但是,有相应的工具(例如ReSharper)。
  • 可维护性(我的看法)

    • string.Format更具可读性,因为它专注于我想表达的句子,例如,在构造漂亮而有意义的错误消息时。使用{N}占位符可为我提供更大的灵活性,以后更容易对其进行修改。
    • 此外,插值中的内联格式说明符易于误读,并且易于在更改期间与表达式一起删除。
    • 使用复杂的长表达式时,插值很快变得更加难以阅读和维护,因此从这种意义上说,当代码不断发展并变得更加复杂时,插值无法很好地扩展。 string.Format不太容易做到这一点。
    • 归根结底,这全是关注点的分离:我不喜欢将应如何呈现应呈现什么混在一起。 / li>

因此,基于这些,我决定在我的大多数代码中坚持使用string.Format。但是,我已经准备了一种扩展方法,使我更喜欢使用一种 fluent 编码方式。该扩展程序的实现是单行的,看起来就像在使用它。

var myErrorMessage = "Value must be less than {0:0.00} for field {1}".FormatWith(maximum, fieldName);

插值是一个很棒的功能,请不要误会我的意思。但是IMO在缺少类似string.Format之类的语言(例如JavaScript)的语言中表现最好。