【问题标题】:Strange localization issue with ArgumentOutOfRangeExceptionArgumentOutOfRangeException 的奇怪本地化问题
【发布时间】:2013-04-27 00:32:28
【问题描述】:

对于以英语为唯一语言的 Windows 版本安装的人来说,这个“问题”可能很难测试/重现。我在安装了“丹麦语(丹麦)”("da-DK" 文化)、.NET 4.5 版的 Windows 7 机器上执行此操作。

我遇到了以下令人惊讶的行为。代码:

Console.WriteLine("Now using intalled UI culture");
Thread.CurrentThread.CurrentUICulture = CultureInfo.InstalledUICulture;
Console.WriteLine(new ArgumentNullException().Message);
Console.WriteLine(new ArgumentOutOfRangeException().Message);

Console.WriteLine();

Console.WriteLine("Now using invariant culture");
Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
Console.WriteLine(new ArgumentNullException().Message);
Console.WriteLine(new ArgumentOutOfRangeException().Message);

产生以下输出:

Now using intalled UI culture
En værdi må ikke være null.
Det angivne argument lå uden for det gyldige værdiområde.

Now using invariant culture
Value cannot be null.
Det angivne argument lå uden for det gyldige værdiområde.

说明:在第一部分中,当 UI 线程是丹麦语时,我们看到了两条本地化异常消息。但在第二部分中,我们看到一条英文(“不变”)消息和一条丹麦文消息,即使 UI 文化不再与丹麦文相关。

我也尝试了很多其他 mscorlib 异常类,看起来只有 System.ArgumentOutOfRangeException 不尊重 UI 文化的变化。

为什么ArgumentOutOfRangeException 在这方面与其他异常不同?

(如果其他人(其他版本的操作系统和框架,和/或其他语言)看到相同的行为会很有趣。)

PS!将以下行粘贴到同一台机器上的 PowerShell(针对另一个 .NET 版本)中会出现ArgumentOutOfRangeException?!

相反问题
[Threading.Thread]::CurrentThread.CurrentUICulture = [Globalization.CultureInfo]::InstalledUICulture; New-Object ArgumentNullException;
[Threading.Thread]::CurrentThread.CurrentUICulture = [Globalization.CultureInfo]::InstalledUICulture; New-Object ArgumentOutOfRangeException;
[Threading.Thread]::CurrentThread.CurrentUICulture = [Globalization.CultureInfo]::InvariantCulture; New-Object ArgumentNullException;
[Threading.Thread]::CurrentThread.CurrentUICulture = [Globalization.CultureInfo]::InvariantCulture; New-Object ArgumentOutOfRangeException;

(保留较长的行以确保每行的两个语句都由 PowerShell 在同一个线程上执行。)

【问题讨论】:

标签: c# .net exception localization internationalization


【解决方案1】:

如果您查看这两个异常的源代码,您会很快发现问题所在。这里是ArgumentNullException的构造函数:

public ArgumentNullException() : 
           base(Environment.GetResourceString("ArgumentNull_Generic")) {
    base.SetErrorCode(-2147467261);
}

如您所见,每次从资源中加载错误消息。 ArgumentOutOfRangeException 的构造函数看起来像这样:

public ArgumentOutOfRangeException() : base(RangeMessage) {
    base.SetErrorCode(-2146233086);
}

其中RangeMessage 是私有静态属性:

private static string RangeMessage {
    get {
        if(_rangeMessage == null) {
            _rangeMessage = Environment.GetResourceString(
                                        "Arg_ArgumentOutOfRangeException");
        }
        return _rangeMessage;
    }
}

这里你可以看到错误信息被缓存的问题。所以不会更新。我看到的唯一方法是通过反射访问 private static volatile string _rangeMessage; 并将其设置回 null

【讨论】:

  • 啊,这很好地解释了它。我在 PowerShell 中看到“相反”行为的原因是我先在同一个 shell 中进行了一些实验,并且碰巧用英语语言文化的线程实例化了第一个 ArgumentOutOfRangeException。所有线程都使用static 缓存字段,无论它们的文化是什么。当我打开一个“新的”PowerShell 应用程序并粘贴四行代码时,我看到了与 C# 应用程序相同的行为。这是一个错误。当前 UI 文化不同时不应保留缓存。将其报告为错误。
猜你喜欢
  • 2015-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多