如何在非英语 Windows 的 C# 插值字符串中将 NumberDecimalSeparator 更改为点

How to change NumberDecimalSeparator to a dot in C# interpolated strings for non-english Windows

提问人:Alexander Farber 提问时间:7/19/2023 最后编辑:Alexander Farber 更新时间:7/19/2023 访问量:52

问:

我已经为我的问题准备了一个 C# 小提琴,但它并没有真正显示实际问题,并且正确地使用点作为插值双精度值中的小数分隔符(用 Tim 的技巧更新,谢谢):

using System;
using System.Linq;

public class Program
{
    readonly static (double lng, double lat)[] Locations = 
    {
        (10.757938, 52.437444),
        (10.764379, 52.437314),
        (10.770562, 52.439067),
        (10.773268, 52.436633),
    };
    
    public static void Main()
    {
        string lngLats = Locations.Aggregate(string.Empty, (str, next) => str + $"{next.Item1:F6},{next.Item2:F6};");
        Console.WriteLine($"lngLats: {lngLats}\n");
        
        double x = 12.3456;
        Console.WriteLine($"A double value: {x}\n");
    }
}

但是,当我使用 Visual Studio 2022 在 Windows 10 企业版 22H2 计算机上运行相同的代码(设置为英语,但德语区域)时,小数点分隔符是一个逗号:

screenshot VS 2022

我的问题是:如何确保小数点分隔符始终是插值字符串中的一个点?

C# .net-core cultureinfo 字符串插值 invariantculture

评论

1赞 Tim Schmelter 7/19/2023
如果您将小提琴更改为将其作为第一行,您也可以在那里重现它:System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo("de-DE");

答:

2赞 Tim Schmelter 7/19/2023 #1

字符串插值使用当前区域性。因此,您需要以下解决方法:double.ToString

double x = 12.3456;
string result = x.ToString(System.Globalization.CultureInfo.InvariantCulture);
Console.WriteLine($"A double value: {result}\n");

你修改过的小提琴:https://dotnetfiddle.net/BTaONq

因此,字符串插值不支持不同的区域性。您可以使用string.Format

Console.WriteLine(string.Format(System.Globalization.CultureInfo.InvariantCulture, "A double value: {0}\n", x));

评论

0赞 Alexander Farber 7/19/2023
当然,蒂姆,我在寻找解决方案时看到了关于方法的建议......但我的问题是,是否有一些技巧可以使字符串插值始终使用点。ToString
0赞 Tim Schmelter 7/19/2023
@AlexanderFarber:没有。然后你需要使用 .将其添加到我的答案中String.Format
2赞 Fildor 7/19/2023
但是,设置当前的文化难道不起作用吗?就像您对问题的评论一样,@TimSchmelter,仅将其设置为不变?
0赞 Tim Schmelter 7/19/2023
@Fildor-standswithMods:当然,那行得通。但它的影响更大,OP 只想修改这个字符串,而不是改变文化。与简单地使用正确的 tool() 相比有什么好处?double.ToString
2赞 Tim Schmelter 7/19/2023
@AlexanderFarber:好吧,不需要使用完整的命名空间就足够了,但我同意这不如使用字符串插值那么好。我会为双精度添加另一行。ToString,然后在插值字符串中使用它。这使得它非常清晰和可读(也在调试器中)。但是如果你喜欢单行,你也可以在字符串中使用,所以CultureInfo.InvariantCulturex.ToString(CultureInfo.InvariantCulture)Console.WriteLine($"A double value: {x.ToString(CultureInfo.InvariantCulture)}\n");
2赞 Olivier Jacot-Descombes 7/19/2023 #2

您可以像这样使用固定区域性

string result1 = FormattableString.Invariant($"lngLats: {lngLats}\n");
string result2 = FormattableString.Invariant($"A double value: {x}\n");

使用 a,您可以简化调用,当然也可以将其与控制台输出集成:using static System.FormattableString;

string lngLats = Locations.Aggregate(
    string.Empty,
    (str, next) => str + Invariant($"{next.Item1:F6},{next.Item2:F6};")
);
Console.WriteLine($"lngLats: {lngLats}\n");

double x = 12.3456;
Console.WriteLine(Invariant($"A double value: {x}\n"));

另请参阅:

评论

0赞 Alexander Farber 7/19/2023
同样,这是一个很好的建议(谢谢,赞成),但它没有建议修复字符串插值的方法$".....{aNumber}..."
0赞 Olivier Jacot-Descombes 7/19/2023
好吧,同样的解决方案也适用于那个。
1赞 Fildor 7/19/2023 #3

我正在考虑这个妥协,也许吧?

double x = 12.3456;
Console.WriteLine($"A double value: {x.AsInvariant()}\n");

// with

public static string AsInvariant(this double x) =>
   x.ToString(System.Globalization.CultureInfo.InvariantCulture);

评论

1赞 Tim Schmelter 7/19/2023
你可以简单地使用我更喜欢的,因为每个人都看到它在做什么。$"A double value: {x.ToString(CultureInfo.InvariantCulture)}\n"
0赞 Fildor 7/19/2023
虽然我同意,但 OP 想要一些短小精悍的东西......恐怕这不会给我们留下一个干净令人满意的答案。