Mårten Rånge
Mårten Rånge
CC#
Created by Mårten Rånge on 10/3/2024 in #help
Forwarding calls to string.Create with custom culture info.
Hi. I have been trying to create a method to help us to do string interpolation using invariant culture. string interpolation picks up the current thread culture when formatting numbers and such and that can lead to surprises.
// x might be "0.00" but on my machine it is "0,00"
var x = $"{0.00:0.00}";
// x might be "0.00" but on my machine it is "0,00"
var x = $"{0.00:0.00}";
We can use string.Create to specify a culture info such as
// x will always be "0.00"
var x = string.Create(CultureInfo.InvariantCulture, $"{0.00:0.00}");
// x will always be "0.00"
var x = string.Create(CultureInfo.InvariantCulture, $"{0.00:0.00}");
But asking people to type string.Create(CultureInfo.InvariantCulture, whenever they do string interpolation will just be ignored. I thought I could make a little method called Inv that thanks to using static allows me to type:
using static StringInterpolation;
Console.WriteLine(Inv($"{0.00:0.00}"));

static class StringInterpolation
{
public static string Inv(ref DefaultInterpolatedStringHandler handler)
{
return string.Create(CultureInfo.InvariantCulture, ref handler);
}
}
using static StringInterpolation;
Console.WriteLine(Inv($"{0.00:0.00}"));

static class StringInterpolation
{
public static string Inv(ref DefaultInterpolatedStringHandler handler)
{
return string.Create(CultureInfo.InvariantCulture, ref handler);
}
}
The problem is that this won't work for me. TBH I don't really understand why it doesn't work since I am just creating a method around string.Create. It seems it uses the current thread culture and ignores me passing the invariant culture. Looking at string.Create
public static string Create(IFormatProvider? provider, [InterpolatedStringHandlerArgument(nameof(provider))] ref DefaultInterpolatedStringHandler handler) =>
handler.ToStringAndClear();
public static string Create(IFormatProvider? provider, [InterpolatedStringHandlerArgument(nameof(provider))] ref DefaultInterpolatedStringHandler handler) =>
handler.ToStringAndClear();
So this method doesn't even use the provider in the implementation. Probably it's related to the attribute [InterpolatedStringHandlerArgument(nameof(provider))] I tried a few options but I hit the post limit so I can't show them. I would like to avoid setting thread culture (global variables in 2024?) or using FormattableString (perf). So I ran out of ideas I thought I check here if someone else has some ideas.
5 replies