|
15,7 |
15,7 |
|
|
|
|
インバリアントカルチャ以外にも、&msdn(netfx,member,System.StringComparison.InvariantCulture){StringComparison.InvariantCulture};や&msdn(netfx,member,System.Text.RegularExpressions.RegexOptions.CultureInvariant){RegexOptions.CultureInvariant};などのオプション、&msdn(netfx,member,System.String.ToUpperInvariant){String.ToUpperInvariantメソッド};といったメソッドなど、インバリアントカルチャの定義に従った動作、つまりカルチャに依存しない動作を行うものも用意されています。
|
インバリアントカルチャ以外にも、&msdn(netfx,member,System.StringComparison.InvariantCulture){StringComparison.InvariantCulture};や&msdn(netfx,member,System.Text.RegularExpressions.RegexOptions.CultureInvariant){RegexOptions.CultureInvariant};などのオプション、&msdn(netfx,member,System.String.ToUpperInvariant){String.ToUpperInvariantメソッド};といったメソッドなど、インバリアントカルチャの定義に従った動作、つまりカルチャに依存しない動作を行うものも用意されています。
|
|
|
|
~ |
ここでは、[[CultureInfoの動作とカルチャに依存した動作・結果となる例>#CultureInfo_culture_aware_behaviors]]とインバリアントカルチャの使用について解説します。 カルチャの取得・変更やカルチャの種類、システムロケールとの対応、CultureInfoから取得できる情報などについては[[programming/netfx/locale/0_abstract]]を参照してください。
|
ここでは、[[CultureInfoの動作とカルチャに依存した動作・結果となる例>#CultureInfo_culture_aware_behaviors]]について解説します。 カルチャの取得・変更やカルチャの種類、システムロケールとの対応、CultureInfoから取得できる情報などについては[[programming/netfx/locale/0_abstract]]を参照してください。
|
|
|
|
|
以下、この文章における実行結果は、ランタイムや実行環境、特に設定されている言語によって結果が異なる箇所があります。 その場合は前提条件を明記するようにしていますが、特に明記しない場合は日本語/日本の環境での実行結果となります。
|
以下、この文章における実行結果は、ランタイムや実行環境、特に設定されている言語によって結果が異なる箇所があります。 その場合は前提条件を明記するようにしていますが、特に明記しない場合は日本語/日本の環境での実行結果となります。
|
|
|
|
|
63,19 |
63,16 |
|
|
|
|
.NETにおける[[デフォルトのカルチャはシステムロケールに基づく>programming/netfx/locale/0_abstract#system_locale_and_initial_culture]]ため、こういった問題は「自環境・一部の環境では期待通りに動作するが、他の環境では正しく動作しない・例外が発生する」といった事象として発覚することになります。
|
.NETにおける[[デフォルトのカルチャはシステムロケールに基づく>programming/netfx/locale/0_abstract#system_locale_and_initial_culture]]ため、こういった問題は「自環境・一部の環境では期待通りに動作するが、他の環境では正しく動作しない・例外が発生する」といった事象として発覚することになります。
|
|
|
|
~ |
特定のカルチャ、特に''システムロケールに依存しない動作とする''、''書式の違いに起因する齟齬を避ける''ためには、[[ローカライズされない書式>programming/netfx/string_formatting/0_formatstrings]]を使用する、文字列比較・ソートでは[[序数(コードポイント)による比較>programming/netfx/string/2_1_comparison#String.CompareOrdinal]]([[StringComparison.Ordinal>programming/netfx/string/2_2_compareoptions#StringComparison.CurrentCulture_vs_StringComparison.Ordinal]])を行うほかに、''インバリアントカルチャを使用する''ことが挙げられます。 以下、この文章ではインバリアントカルチャを使用する場合を中心に解説します。
|
特定のカルチャ、特に''システムロケールに依存しない動作とする''、''書式の違いに起因する齟齬を避ける''ためには、方法の一つとしてインバリアントカルチャの使用が挙げられます。
|
|
|
|
- |
|
**カルチャごとの動作とプラットフォーム・ランタイムによる差異 [#runtime_platform_differences]
|
- |
|
場合によっては、システムロケールだけでなく、プラットフォーム・ランタイムの種類による差異も齟齬の原因となる場合があります。
|
|
|
|
~ |
**カルチャごとの動作とランタイム・プラットフォームによる差異 [#runtime_platform_differences]
|
.NET Core/.NETでは、Windows上ではWindows OSによって提供されるカルチャ情報を使用する一方、Linux上では[[ICU(libicu):http://site.icu-project.org/]]によって得られるカルチャ情報を使用するとされています。 このため、同一のロケールであっても異なる動作となる場合があります。
|
+ |
カルチャ(CultureInfo)として定義される書式や規則は、プラットフォームのAPIや他のライブラリなどから取得されます。 このため、システムロケールだけでなく、ランタイムの種類(.NET/.NET Core/.NET Framework)、実行されるプラットフォームによる差異も、書式の違いによる齟齬や環境ごとに異なる動作の原因となる場合があります。
|
|
+ |
|
|
+ |
Windows上では、[[ICU(libicu):http://site.icu-project.org/]]によって得られるカルチャ情報(ICUがインストールされている場合・.NETのみ)、もしくはWindows OSのNSL(National Language Support)によって得られるカルチャ情報(.NET/.NET Core/.NET Frameworkの場合)を使用します。 加えて、仮にICUが使用できる環境であっても、環境変数・プロジェクト設定によってNSLを使用するように変更することができます。 一方、Linux上では(常に)ICUによって得られるカルチャ情報を使用するとされています。 (詳細は章末)
|
|
+ |
|
|
+ |
このため、仮に同一のロケールであっても、また''インバリアントカルチャも含め''、ランタイムの種類・プラットフォーム・ICUのインストール使用可否等、構成・設定により異なる動作となる場合があります。
|
|
|
|
|
|
例えば、次のコードは、同じロケール``ar-AE``であっても、ランタイムの種類によって異なる結果となります。
|
例えば、次のコードは、同じロケール``ar-AE``であっても、ランタイムの種類によって異なる結果となります。
|
|
|
|
~ |
$samplecode(lang=c#-9.0,copyright-year=2020,数値の文字列化におけるカルチャに依存した動作とプラットフォーム・ランタイムによる差異)
|
$samplecode(lang=c#-9.0,copyright-year=2020,カルチャに依存した動作とプラットフォーム・ランタイムによる差異)
|
|
#code{{
|
#code{{
|
|
using System;
|
using System;
|
|
using System.Globalization;
|
using System.Globalization;
|
|
123,80 |
120,6 |
|
}}
|
}}
|
|
$samplecode$
|
$samplecode$
|
|
|
|
+ |
また、次のコードは、インバリアントカルチャを使用した場合でもランタイムの種類によって異なる結果となります。
|
|
+ |
|
|
+ |
$samplecode(lang=c#-9.0,copyright-year=2020,文字列配列のソートにおけるインバリアントカルチャの動作とプラットフォーム・ランタイムによる差異)
|
|
+ |
#code{{
|
|
+ |
using System;
|
|
+ |
using System.Globalization;
|
|
+ |
using System.Linq;
|
|
+ |
|
|
+ |
// 現在のカルチャをインバリアントカルチャにする
|
|
+ |
CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;
|
|
+ |
// あるいはIComparer<string>としてStringComparer.InvariantCultureを指定しても同じ
|
|
+ |
|
|
+ |
// 文字列配列を並べ替えて表示する
|
|
+ |
Console.WriteLine(
|
|
+ |
string.Join(", ", new[] {"あ", "ア", "亜", "ア", "A", "A"}.OrderBy(s => s/*, StringComparer.InvariantCulture*/))
|
|
+ |
);
|
|
+ |
Console.WriteLine(
|
|
+ |
string.Join(", ", new[] {"0-0", "00-0", "00-00", "0-00", "0-1", "0-01", "0-10"}.OrderBy(s => s/*, StringComparer.InvariantCulture*/))
|
|
+ |
);
|
|
+ |
|
|
+ |
// 比較として、序数(コードポイント)による比較によって並べ替えた場合
|
|
+ |
Console.WriteLine();
|
|
+ |
Console.WriteLine("[Ordinal]");
|
|
+ |
Console.WriteLine(
|
|
+ |
string.Join(", ", new[] {"あ", "ア", "亜", "ア", "A", "A"}.OrderBy(s => s, StringComparer.Ordinal))
|
|
+ |
);
|
|
+ |
Console.WriteLine(
|
|
+ |
string.Join(", ", new[] {"0-0", "00-0", "00-00", "0-00", "0-1", "0-01", "0-10"}.OrderBy(s => s, StringComparer.Ordinal))
|
|
+ |
);
|
|
+ |
}}
|
|
+ |
$samplecode(tab-title=.NET 5/Windows 10)
|
|
+ |
#prompt{{
|
|
+ |
A, A, あ, ア, ア, 亜
|
|
+ |
0-0, 0-00, 0-01, 0-1, 0-10, 00-0, 00-00
|
|
+ |
|
|
+ |
[Ordinal]
|
|
+ |
A, あ, ア, 亜, A, ア
|
|
+ |
0-0, 0-00, 0-01, 0-1, 0-10, 00-0, 00-00
|
|
+ |
}}
|
|
+ |
$samplecode(tab-title=.NET Framework 4.8/Windows 10)
|
|
+ |
#prompt{{
|
|
+ |
A, A, ア, ア, あ, 亜
|
|
+ |
0-0, 00-0, 0-00, 00-00, 0-01, 0-1, 0-10
|
|
+ |
|
|
+ |
[Ordinal]
|
|
+ |
A, あ, ア, 亜, A, ア
|
|
+ |
0-0, 0-00, 0-01, 0-1, 0-10, 00-0, 00-00
|
|
+ |
}}
|
|
+ |
$samplecode(tab-title=.NET 5/Ubuntu 20.04)
|
|
+ |
#prompt{{
|
|
+ |
A, A, あ, ア, ア, 亜
|
|
+ |
0-0, 0-00, 0-01, 0-1, 0-10, 00-0, 00-00
|
|
+ |
|
|
+ |
[Ordinal]
|
|
+ |
A, あ, ア, 亜, A, ア
|
|
+ |
0-0, 0-00, 0-01, 0-1, 0-10, 00-0, 00-00
|
|
+ |
}}
|
|
+ |
$samplecode(tab-title=Mono 6.12/Ubuntu 20.04)
|
|
+ |
#prompt{{
|
|
+ |
A, A, ア, ア, あ, 亜
|
|
+ |
0-0, 00-0, 0-00, 00-00, 0-01, 0-1, 0-10
|
|
+ |
|
|
+ |
[Ordinal]
|
|
+ |
A, あ, ア, 亜, A, ア
|
|
+ |
0-0, 0-00, 0-01, 0-1, 0-10, 00-0, 00-00
|
|
+ |
}}
|
|
+ |
$samplecode$
|
|
+ |
|
|
+ |
このほかにも、DateTimeにおける書式指定子``D``など、書式よっては.NET Frameworkと.NET Core/.NETで表記に差異があるものがあり、これにより齟齬の原因となる場合があります。
|
|
+ |
|
|
+ |
|
|
+ |
|
|
+ |
なお、カルチャ情報(CultureInfoとして定義される書式や規則の情報)は以下のように取得されるとされています。
|
|
+ |
|
|
|
$blockquote(cite-title=CultureInfo クラス (System.Globalization) | Microsoft Docs,cite=https://docs.microsoft.com/ja-jp/dotnet/api/system.globalization.cultureinfo?view=net-5.0)
|
$blockquote(cite-title=CultureInfo クラス (System.Globalization) | Microsoft Docs,cite=https://docs.microsoft.com/ja-jp/dotnet/api/system.globalization.cultureinfo?view=net-5.0)
|
|
#heading(CultureInfo と文化のデータ)
|
#heading(CultureInfo と文化のデータ)
|
|
|
|
|
210,18 |
133,7 |
|
このため、特定の .NET 実装、プラットフォーム、またはバージョンで使用できるカルチャは、別の .NET 実装、プラットフォーム、またはバージョンでは使用できない場合があります。
|
このため、特定の .NET 実装、プラットフォーム、またはバージョンで使用できるカルチャは、別の .NET 実装、プラットフォーム、またはバージョンでは使用できない場合があります。
|
|
$blockquote$
|
$blockquote$
|
|
|
|
~ |
$blockquote(cite-title=グローバリゼーションと ICU | Microsoft Docs,cite=https://docs.microsoft.com/ja-jp/dotnet/standard/globalization-localization/globalization-icu)
|
このほかにも、.NET Frameworkと.NET Core/.NETでは、DateTimeにおける書式指定子``D``など、書式よっては表記に差異があるものがあり、これにより齟齬の原因となる場合があります。
|
+ |
#heading(Windows 上の ICU)
|
|
+ |
|
|
+ |
Windows 10 の 2019 年 5 月更新プログラム以降では、OS の一部として icu.dll が含まれるようになり、.NET 5.0 以降のバージョンでは、既定で ICU が使用されるようになりました。 .NET 5.0 以降のバージョンを Windows で実行する場合、icu.dll の読み込みが試行され、存在する場合、グローバリゼーションの実装で使用されます。 Windows の古いバージョンを実行している場合などで、このライブラリを見つけたり、読み込むことができない場合、.NET 5.0 以降のバージョンは NLS ベースの実装に戻ります。
|
|
+ |
$blockquote$
|
|
+ |
|
|
+ |
$blockquote(cite-title=グローバリゼーションと ICU | Microsoft Docs,cite=https://docs.microsoft.com/ja-jp/dotnet/standard/globalization-localization/globalization-icu)
|
|
+ |
#heading(ICU の代わりに NLS を使用する)
|
|
+ |
|
|
+ |
NLS の代わりに ICU を使用すると、一部のグローバリゼーション関連の操作で動作が違ってしまうことがあります。 開発者は、NLS を使用するように、ICU の実装を戻すことを選択することができます。 アプリケーションでは、次のいずれかの方法で NLS モードを有効にできます。
|
|
+ |
$blockquote$
|
|
+ |
|
|
|
|
|
|
|
|
|
|
|