是否可以以文化不变的方式动态构建弦?

发布于 2025-01-21 11:45:16 字数 1827 浏览 0 评论 0 原文

我正在尝试编写助手方法,以使用 StringBuilder 类。

我希望能够以一种文化不变的方式做到这一点,以便两个具有不同文化的线程获得相同的结果,如果两者都以相同的输入调用助手方法。

不幸的是,许多 StringBuilder 方法默认为当前线程文化,并且没有提供从外部控制格式的方法。一个例子是 appendjoin 方法。

考虑以下代码:

object[] items = { 13.34, new DateTime(2022, 4, 14) };

var builder = new StringBuilder();
builder.AppendJoin(" - ", items);
var message = builder.ToString();

Console.WriteLine(message); 

此代码输出 13.34-4/14/2022 12:00:00 AM 如果线程文化为 en -us 。输出变为 13,34-14/04/2022 00:00:00 如果线程文化为 it -it -it

核心问题是 appendjoin 允许提供 iformatProvider 以控制外部的行为。

基于我的理解,解决此问题的唯一方法是使用 appendformat 方法,它具有 iformatProvider 的过载。

我错过了什么吗?这是解决我的用例的正确方法吗? .NET核心框架中是否有更好的类型可以这样做?

I'm trying to write a helper method to dynamically build a string by using the StringBuilder class.

I want to be able to do that in a culture invariant way so that two threads having different cultures get the same result if both call the helper method with the same input.

Unfortunately, many of the StringBuilder methods default to the current thread's culture and don't provide a way to control the formatting from outside. An example of this is the AppendJoin method.

Consider the following code:

object[] items = { 13.34, new DateTime(2022, 4, 14) };

var builder = new StringBuilder();
builder.AppendJoin(" - ", items);
var message = builder.ToString();

Console.WriteLine(message); 

This code outputs 13.34 - 4/14/2022 12:00:00 AM if the thread culture is en-US. The output becomes 13,34 - 14/04/2022 00:00:00 if the thread culture is it-IT.

The core issue is that there is no overload of AppendJoin allowing to provide an instance of IFormatProvider to control the behavior from outside.

Based on my understanding, the only way to work around this is to use the AppendFormat method, which has overloads that take IFormatProvider.

Am I missing anything? Is this the right way to solve my use case? Is there a better type in the .NET Core framework to do so?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夏花。依旧 2025-01-28 11:45:16

除了使用附录外形外,这里还有几种替代方法要考虑:

  1. 在您的帮助方法中,暂时将当前线程的文化更改为cultureinfo.invariantculture,将弦乐定义方法称为往常,然后恢复原始文化。<<<<<<<<<。 /p>

  2. 将您传递给StringBuilder的每个值包裹在迫使使用不变文化的对象中:

public class InvariantWrapper : IFormattable
{
    private readonly object _value;

    public InvariantWrapper(object value)
    {
        _value = value;
    }

    public override string ToString()
    {
        return this.ToString(null, null);
    }

    public string ToString(string format, IFormatProvider formatProvider)
    {
        return _value switch
        {
            IFormattable formattable => formattable.ToString(format, CultureInfo.InvariantCulture),
            not null => _value.ToString(),
            null => ""
        };
    }
}

示例用法:

builder.AppendJoin(" - ", items.Select(item => new InvariantWrapper(item)));

注意: switch 表达式在C#8.0中引入,而 not Null 模式是在C#9.0中引入的。如果您使用的是C#7.x,则可以使用以下代码:

return _value is IFormattable formattable
    ? formattable.ToString(format, CultureInfo.InvariantCulture)
    : _value != null
        ? _value.ToString()
        : "";

Besides using AppendFormat, here are a couple of alternative approaches to consider:

  1. In your helper method, temporarily change the culture of the current thread to CultureInfo.InvariantCulture, call the StringBuilder methods as usual, and then restore the original culture.

  2. Wrap each of the values you pass to StringBuilder in an object that forces the use of the invariant culture:

public class InvariantWrapper : IFormattable
{
    private readonly object _value;

    public InvariantWrapper(object value)
    {
        _value = value;
    }

    public override string ToString()
    {
        return this.ToString(null, null);
    }

    public string ToString(string format, IFormatProvider formatProvider)
    {
        return _value switch
        {
            IFormattable formattable => formattable.ToString(format, CultureInfo.InvariantCulture),
            not null => _value.ToString(),
            null => ""
        };
    }
}

Sample usage:

builder.AppendJoin(" - ", items.Select(item => new InvariantWrapper(item)));

Note: The switch expression was introduced in C# 8.0 and the not null pattern was introduced in C# 9.0. If you’re using C# 7.x, you can use the following code instead:

return _value is IFormattable formattable
    ? formattable.ToString(format, CultureInfo.InvariantCulture)
    : _value != null
        ? _value.ToString()
        : "";
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文