Daily Knowledge Drop
Introduced in C# 10 (.NET 6), the String.Create
method can be used to evaluate an interpolated string to a specific culture (including the invariant culture). This method is faster, and uses less resources than the previously available method of using FormattableString
.
FormattableString
Invariant
Prior to C# 10 FormattableString
was the method used, and evaluating an interpolated string to invariant culture was fairly straightforward:
private decimal decValue = 1.99m;
private DateTime dateValue = DateTime.UtcNow;
// output the default interpolated string
Console.WriteLine($"Decimal: {decValue} | Date: {dateValue}");
// output the string formatted to "invariant culture"
Console.WriteLine(FormattableString.Invariant(
$"Decimal: {decValue} | Date: {dateValue}"));
The output of the above:
Decimal: 1,99 | Date: 2022/09/12 03:49:41
Decimal: 1.99 | Date: 09/12/2022 03:49:41
Culture specific
Evaluating an interpolated string to a specific culture is slightly more complicated when using FormattableString
:
private decimal decValue = 1.99m;
private DateTime dateValue = DateTime.UtcNow;
// output the default interpolated string
Console.WriteLine($"Decimal: {decValue} | Date: {dateValue}");
// output the string formatted in the specific culture
// first declare the FormattableString
FormattableString formattable = $"Decimal: {decValue} | Date: {dateValue}";
// ToString specifying the culture
Console.Write(formattable.ToString(CultureInfo.GetCultureInfo("en-US")));
The output of the above:
Decimal: 1,99 | Date: 2022/09/12 04:00:47
Decimal: 1.99 | Date: 9/12/2022 4:00:47 AM
String.Create
Invariant
The new String.Create
method introduced in .NET6 with C# 10, simplifies the evaluation of a interpolated string to a specific culture:
private decimal decValue = 1.99m;
private DateTime dateValue = DateTime.UtcNow;
// output the default interpolated string
Console.WriteLine($"Decimal: {decValue} | Date: {dateValue}");
// output string with the specific culture (invariant)
Console.WriteLine(String.Create(CultureInfo.InvariantCulture,
$"Decimal: {decValue} | Date: {dateValue}"));
The output of the above (which is the same as when using FormattableString.Invariant above):
Decimal: 1,99 | Date: 2022/09/12 04:02:59
Decimal: 1.99 | Date: 09/12/2022 04:02:59
Culture specific
Specifying a specific culture with String.Create
is just as simple as specifying InvariantCulture, and definitely simpler than the FormattableString equivalent:
private decimal decValue = 1.99m;
private DateTime dateValue = DateTime.UtcNow;
// output the default interpolated string
Console.WriteLine($"Decimal: {decValue} | Date: {dateValue}");
// output string with the specific culture (en-US)
Console.WriteLine(String.Create(CultureInfo.GetCultureInfo("en-US"),
$"Decimal: {decValue} | Date: {dateValue}"));
The output of the above (which is the same as when using FormattableString with the specific culture above):
Decimal: 1,99 | Date: 2022/09/12 04:05:15
Decimal: 1.99 | Date: 9/12/2022 4:05:15 AM
Performance
Using BenchmarkDotNet
to compare the speed and memory usage of the above 4 methods, we can see that in all cases, using the String.Create version is faster, and uses less memory
than the FormattableString versions:
Method | Mean | Error | StdDev | Gen0 | Allocated |
---|---|---|---|---|---|
StringFormatterInvariant | 342.6 ns | 4.92 ns | 4.60 ns | 0.0367 | 232 B |
StringFormatterCulture | 400.2 ns | 7.81 ns | 9.87 ns | 0.0429 | 272 B |
StringCreateInvariant | 272.5 ns | 3.86 ns | 3.42 ns | 0.0162 | 104 B |
StringCreateCulture | 326.5 ns | 4.41 ns | 3.91 ns | 0.0229 | 144 B |
Notes
Even though the performance and memory improvements are slight (nano-seconds and bytes), if your application is making heavy use of FormattableString
to format strings to specific cultures, then there are gains to be had by converting to using String.Create
.
References
Performance: string.Create vs FormattableString
Daily Drop 176: 06-10-2022
At the start of 2022 I set myself the goal of learning one new coding related piece of knowledge a day.
It could be anything - some.NET / C# functionality I wasn't aware of, a design practice, a cool new coding technique, or just something I find interesting. It could be something I knew at one point but had forgotten, or something completely new, which I may or may never actually use.
The Daily Drop is a record of these pieces of knowledge - writing about and summarizing them helps re-enforce the information for myself, as well as potentially helps others learn something new as well.