Far*_*ani 12 c# .net-core .net-5
当我在 .NET Core 3.1 中运行以下代码时,我得到6了返回值。
// .NET Core 3.1
string s = "Hello\r\nworld!";
int idx = s.IndexOf("\n");
Console.WriteLine(idx);
Run Code Online (Sandbox Code Playgroud)
结果:
6
Run Code Online (Sandbox Code Playgroud)
但是当我在 .NET 5.0 中运行这段代码时,我得到了不同的结果。为什么会发生这种情况?
6
Run Code Online (Sandbox Code Playgroud)
结果:
-1
Run Code Online (Sandbox Code Playgroud)
Gyö*_*zeg 14
评论和@Ray 的回答包含了原因。
尽管破解.csprojorruntimeconfig.json文件可能会节省您的时间,但真正的解决方案是明确指定比较:
// this returns the expected result
int idx = s.IndexOf("\n", StringComparison.Ordinal);
Run Code Online (Sandbox Code Playgroud)
由于某些原因,IndexOf(string)默认使用当前区域性比较,当您的应用程序在与您的区域设置不同的环境中执行时,即使使用较早的 .NET 版本也可能会导致意外。
使用特定于文化的搜索实际上是一种非常罕见的场景(例如,可以在浏览器、图书阅读器或 UI 搜索中有效)并且它比顺序搜索慢得多。
同样的问题也适用于StartsWith/ EndsWith/ Contains/ ToUpper/ToLower甚至ToString和Parseformattable类型的方法(尤其是使用浮点类型时),因为这些也默认使用当前的文化,这可以有很多陷阱的来源。但是,如果您不使用特定的比较或文化,最近的代码分析器(例如 FxCop、ReSharper)会警告您。建议在产品代码中为这些问题设置高严重性。
您的示例代码与MSDN上发布的代码完全匹配,该代码还描述了为什么以及如何在这些摘录中恢复到旧行为(重点是我的):
过去,.NET 全球化 API 在不同平台上使用不同的底层库。在 Unix 上,API 使用Unicode 国际组件 (ICU),而在 Windows 上,它们使用国家语言支持 (NLS)。[...]这些领域的行为差异很明显:
- 文化和文化数据
- 字符串套管
- 字符串排序和搜索
- 排序键
- 字符串规范化
- 国际化域名 (IDN) 支持
- Linux 上的时区显示名称
要恢复使用 NLS [与 Windows 2019 年 5 月 10 日更新和更新版本相关,现在默认使用 ICU ],开发人员可以选择退出 ICU 实施。应用程序可以通过以下任一方式启用 NLS 模式:
在项目文件中:
Run Code Online (Sandbox Code Playgroud)<ItemGroup> <RuntimeHostConfigurationOption Include="System.Globalization.UseNls" Value="true" /> </ItemGroup>在
runtimeconfig.json文件中:Run Code Online (Sandbox Code Playgroud){ "runtimeOptions": { "configProperties": { "System.Globalization.AppLocalIcu": "<suffix>:<version> or <version>" } } }通过将环境变量
DOTNET_SYSTEM_GLOBALIZATION_APPLOCALICU设置为值<suffix>:<version>或<version>.
<suffix>: 长度少于 36 个字符的可选后缀,遵循公共 ICU 打包约定。在构建自定义 ICU 时,您可以对其进行自定义以生成 lib 名称和导出的符号名称以包含后缀,例如 libicuucmyapp,其中 myapp 是后缀。
<version>:有效的 ICU 版本,例如 67.1。此版本用于加载二进制文件并获取导出的符号。
有关更多/最新信息,请参阅上面的 MSDN 链接。
但是,我建议您也阅读György K?szeg 的回答,因为您只需从不精确的字符串操作开始担心这些细节。
| 归档时间: |
|
| 查看次数: |
832 次 |
| 最近记录: |