Skip to content

Instantly share code, notes, and snippets.

@ufcpp
Created October 31, 2020 12:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ufcpp/e0e088848b24b7d9393b9ce0dec46530 to your computer and use it in GitHub Desktop.
Save ufcpp/e0e088848b24b7d9393b9ce0dec46530 to your computer and use it in GitHub Desktop.

.NET 5.0 でのカルチャー依存文字列比較:

  • Windows は NLS っていうライブラリを持ってて、これまで Windows 版の .NET Core はこれを使ってた。
  • これまでも、非 Windows 環境の .NET Core は ICU っていうライブラリ(デファクト標準)を使ってた。
  • .NET 5.0 で、Windows 上でも ICU を使うようになった。

一応、.NET 5.0 でも以下の設定を csproj に入れれば NLS 挙動に戻せはする。

  <ItemGroup>
    <RuntimeHostConfigurationOption Include="System.Globalization.UseNls" Value="true" />
  </ItemGroup>

なので、

  • Windows かどうか
  • .NET Core 3.1 以前か .NET 5 以降か
  • (.NET 5 では) UseNls オプションを入れるかどうか

で挙動が変わる。

なお悪いことに、

  • IndexOf(string) は CurrentCulture を見た文字列比較
  • Contains は Ordinal 比較(カルチャーとか関係なく、単純に Unicode 符号点の数値で比較)

と、メソッドごとにデフォルト挙動が違うそうで…

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<!-- ↓ この行の有無で挙動が変わる -->
<RuntimeHostConfigurationOption Include="System.Globalization.UseNls" Value="true" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Globalization" Version="4.3.0" />
</ItemGroup>
</Project>
using System;
using System.Globalization;
using System.Text;
using System.Threading;
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
// 以下、NLS の時は 0 とか 1 とか、ICU の時は全部 -1 が表示される。
foreach (var (cultureName, s1, s2) in new[]
{
// これが一番やばそう。
// ICU (というか Unicode 標準)では CRLF は不可分とのこと。
("", "\r\n", "\n"),
// この辺りは古英語では使ってたっぽいからまだ InvariantCulture でもわかる。
("", "æ", "ae"),
("", "œ", "oe"),
// InvariantCulture (ロケールに依存しない言語)とは一体…
// ß はドイツ語固有なのに、別に de-De じゃなくても一致判定受けてたみたい。
("", "ß", "ss"),
// バックスラッシュ問題…
// 特定言語でだけ一致判定されてそう。
("ja-Jp", "\\", "¥"),
("ko-Kr", "\\", "₩"),
})
{
var culture = CultureInfo.GetCultureInfo(cultureName);
Thread.CurrentThread.CurrentCulture = culture;
Console.WriteLine(s1.IndexOf(s2)); // CurrentCulture 依存
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment