Runtime: 从.NET Core 3.0-> .NET 5.0的string.IndexOf(string)更改更改

创建于 2020-10-22  ·  76评论  ·  资料来源: dotnet/runtime

描述

我正在扩展程序包以支持.NET 5.0,并且遇到了重大变化。 给定控制台应用程序:

using System;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            var actual = "Detail of supported commands\n============\n## Documentation produced for DelegateDecompiler, version 0.28.0 on Thursday, 22 October 2020 16:03\n\r\nThis file documents what linq commands **DelegateDecompiler** supports when\r\nworking with [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/) (EF).\r\nEF has one of the best implementations for converting Linq `IQueryable<>` commands into database\r\naccess commands, in EF's case T-SQL. Therefore it is a good candidate for using in our tests.\r\n\r\nThis documentation was produced by compaired direct EF Linq queries against the same query implemented\r\nas a DelegateDecompiler's `Computed` properties. This produces a Supported/Not Supported flag\r\non each command type tested. Tests are groups and ordered to try and make finding things\r\neasier.\r\n\r\nSo, if you want to use DelegateDecompiler and are not sure whether the linq command\r\nyou want to use will work then clone this project and write your own tests.\r\n(See [How to add a test](HowToAddMoreTests.md) documentation on how to do this). \r\nIf there is a problem then please fork the repository and add your own tests. \r\nThat will make it much easier to diagnose your issue.\r\n\r\n*Note: The test suite has only recently been set up and has only a handful of tests at the moment.\r\nMore will appear as we move forward.*\r\n\r\n\r\n### Group: Unit Test Group\n#### [My Unit Test1](../TestGroup01UnitTestGroup/Test01MyUnitTest1):\n- Supported\n  * Good1 (line 1)\n  * Good2 (line 2)\n\r\n#### [My Unit Test2](../TestGroup01UnitTestGroup/Test01MyUnitTest2):\n- Supported\n  * Good1 (line 1)\n  * Good2 (line 2)\n\r\n\r\n\nThe End\n";

            var expected = "\n#### [My Unit Test2](";

            Console.WriteLine($"actual.Contains(expected): {actual.Contains(expected)}");
            Console.WriteLine($"actual.IndexOf(expected): {actual.IndexOf(expected)}");
        }
    }
}

基于.NET Core 3.0-> .NET 5.0的运行时,我得到了不同的结果:

.NET Core 3.0:

actual.Contains(expected): True
actual.IndexOf(expected): 1475

.NET 5.0:

actual.Contains(expected): True
actual.IndexOf(expected): -1

组态

Windows 10专业版内部版本19041 x64
.NET Core 3.1.9
.NET 5.0.0-rc.2.20475.5

回归?

是的,它通过.NET Core 3.1.9运作

area-System.Globalization question

最有用的评论

@tarekgh ,我同意ContainsIndexOf之间的不同结果本身并不是问题。

问题显然是IndexOf ,它无法在另一个仅ASCII的字符串中找到一个仅ASCII的字符串(我不确定是否对任何仅ASCII的字符串强加了任何与语言环境有关的行为!)。

从任何与语言环境/ NLS / ICU相关的更改中,我都不会想到这一点。 实际上,我想不出任何其他类似的编程语言/运行时。

这是一个简化的测试用例,在.NET 5 RC 2上损坏了(我的意思是,给我完全出乎意料的结果):

var actual = "\n\r\nTest";
var expected = "\nTest";

Console.WriteLine($"actual.IndexOf(expected): {actual.IndexOf(expected)}"); // => -1

它真的应该那样工作吗? 还有,为什么呢? 它实际上试图做什么?

这真的是有计划的变更吗?

是的,出于各种原因,有意更改为重症监护病房。

抱歉,但是我不相信是计划的更改,因此我想强调:我无法想象有人计划这样的更改。 就像.NET团队的人们坐在一起讨论:

启用了ICU的字符串“ \ n \ r \ nTest”是否包含“ \ nTest”? 不,显然不是!

没有人抱怨吗? 没有机会!

这看起来不像是计划或预期的更改,而是看起来像一个非常严重的错误,一个很大的兼容性阻止程序。 因此,新的和移植的.NET应用程序将无法在新的运行时上正常运行,因为它们将无法在字符串内部找到子字符串!

为什么ICU仍然关心行尾? 某些语言环境是否具有自己的特定于语言环境的行结尾?

PS:是的,您可能会争辩说,应该真的总是调用某种与文化无关的IndexOf变体,例如带有序号的。 但是,如果您决定在.NET 5中很难破解它,

另外,我想我们大家都理解,尽管IndexOf始终以特定于文化的方式运行,但仍有大量代码使用IndexOf而没有顺序标志,并且该代码_用于工作_(至少在某些/大多数情况下)。 .NET 5更新后它将停止工作。

所有76条评论

@tarekgh

标记此区域的订户: @tarekgh@safern ,@krwq
如果要订阅,请参阅area-owners.md中的信息。

这是设计使然,因为在.NET 5.0中,我们已使用ICU而非NLS进行了切换。 您可以查看https://docs.microsoft.com/zh-cn/dotnet/standard/globalization-localization/globalization-icu了解更多详细信息。

您可以选择使用配置开关System.Globalization.UseNls返回到旧的行为,但我们不建议您这样做,因为ICU更正确,并且使用ICU进行升级将使整个操作系统保持一致。

忘了说,如果您希望IndexOf表现为Contains ,那么您应该在那时使用序数比较。

C# actual.IndexOf(expected, StringComparison.Ordinal)

您可以选择使用配置开关System.Globalization.UseNls返回到旧的行为,但是我们不建议您这样做,因为ICU更正确,并且使用ICU进行升级将在整个操作系统之间保持一致性。

是的,如果您在Unix上以netcoreapp3.1目标运行此代码,您将看到以下相同的行为:

 santifdezm  DESKTOP-1J7TFMI  ~  experimental  indexof  $   /home/santifdezm/experimental/indexof/bin/Debug/netcoreapp3.1/linux-x64/publish/indexof
actual.Contains(expected): True
actual.IndexOf(expected): -1

作为@tarekghOrdinal进行比较,它将返回预期结果。

 santifdezm  DESKTOP-1J7TFMI  ~  experimental  indexof  $  /home/santifdezm/experimental/indexof/bin/Debug/net5.0/linux-x64/publish/indexof
actual.Contains(expected): True
actual.IndexOf(expected): 1475

我认为这失败了,因为在源字符串中混合了\r\n\n 。 如果我将\r\n所有实例替换\n它将起作用。 如果我将所有内容制作成\r\n 。 只是混合导致从ICU的比较中得出不同的结果。

Twitter上报告的问题是,在5.0运行时内,使用相同的输入重复调用string.IndexOf会在每次调用中产生不同的结果。

https://twitter.com/jbogard/status/1319381273585061890?s=21

编辑:上面是一个误会。

@GrabYourPitchforks然后我们可以更新问题标题吗? 由于这是技术性的重大突破,但这会在Windows和Unix上发生...对吗?

我离线对Jimmy进行了ping操作以进行澄清。 我可能误解了他的原始问题报告。 280个字符的论坛在传达错误时并不总是有效的。 ;)

为了澄清起见, Contains API正在执行序数运算。 没有任何字符串比较标志的IndexOf是语言操作,不是序数。 如果要比较包含行为与IndexOf,需要使用IndexOf(expected, StringComparison.Ordinal)
如果需要了解有关差异的更多信息, https://docs.microsoft.com/zh-cn/dotnet/csharp/how-to/compare-strings是有用的链接。

我在Twitter上收到了澄清。 该应用没有循环调用IndexOf 。 这只是标准的3.0与5.0行为差异报告。

@GrabYourPitchforks您可以在Twitter回复上共享链接https://docs.microsoft.com/zh-cn/dotnet/standard/globalization-localization/globalization-icu ,并提到我们有一个配置开关可以恢复到以前的行为吗?

我在Twitter上收到了澄清。 该应用程序未在循环中调用IndexOf。 这只是标准的3.0与5.0行为差异报告。

谢谢,@GrabYourPitchforks ...基于此,按设计将其关闭。

要在此处添加更多内容,如果您希望在不切换回NLS的情况下恢复原来的行为,则可以

C#
CultureInfo.CurrentCulture.CompareInfo.IndexOf(实际,预期,CompareOptions.IgnoreSymbols)


or 

```C#
    actual.IndexOf(expected, StringComparison.Ordinal)

代替

C# actual.IndexOf(expected)

并且您应该得到期望的行为。

我在链接的ICU相关文档(https://docs.microsoft.com/zh-cn/dotnet/standard/globalization-localization/中看不到关于\r\n\n任何信息全球化-icu)。

这真的是有计划的变更吗?

@ForNeVeR很难列出ICU和NLS之间的每个差异。 该文档讨论的是切换到ICU的主要变化。 正如我之前指出的,将不带StringComparison参数的ContainsIndexOf的结果进行比较是不正确的。 如果需要,我在上面列出了几种获得先前行为的方法。 从此问题的报告中,我发现IndexOf的用法应使用Ordinal选项,并且在这种情况下使用语言比较是不正确的。 在这种情况下使用语言比较可能取决于当前的文化,这可能会在不同的环境下产生不同的结果。

这真的是有计划的变更吗?

是的,出于各种原因,有意更改为重症监护病房。 Windows当前正在通过NLS推广使用ICU。 无论如何,ICU是未来。 同样,ICU将提供机会在Windows / Linux / OSX或任何受支持的平台上具有一致的行为。 如果需要,使用ICU将使应用程序有机会自定义全球化行为。

如文档所示,如果愿意,您仍然可以选择切换回旧的行为。

哎呀,引用的文档说Windows上的ICU / NLS行为可能会根据实际环境中的icu.dll可用性而以静默方式切换。 对于已发布的独立应用程序,这可能是一个很大的惊喜。 我希望.NET能够在ICU能够解决此问题的情况下做出决定,因为该开关已被决定,而且ICU并非在所有目标环境中都可用。 这种可选的运行时依赖关系使事情变得更加有趣。

我希望.NET能够在ICU能够解决此问题的情况下做出决定,因为该开关已被决定,而且ICU并非在所有目标环境中都可用。 这种可选的运行时依赖关系使事情变得更加有趣。

ICU现在以NuGet软件包的形式发布。 应用程序可以使用此类程序包来使自包含应用程序具有ICU。 查看doc中的“

@tarekgh ,我同意ContainsIndexOf之间的不同结果本身并不是问题。

问题显然是IndexOf ,它无法在另一个仅ASCII的字符串中找到一个仅ASCII的字符串(我不确定是否对任何仅ASCII的字符串强加了任何与语言环境有关的行为!)。

从任何与语言环境/ NLS / ICU相关的更改中,我都不会想到这一点。 实际上,我想不出任何其他类似的编程语言/运行时。

这是一个简化的测试用例,在.NET 5 RC 2上损坏了(我的意思是,给我完全出乎意料的结果):

var actual = "\n\r\nTest";
var expected = "\nTest";

Console.WriteLine($"actual.IndexOf(expected): {actual.IndexOf(expected)}"); // => -1

它真的应该那样工作吗? 还有,为什么呢? 它实际上试图做什么?

这真的是有计划的变更吗?

是的,出于各种原因,有意更改为重症监护病房。

抱歉,但是我不相信是计划的更改,因此我想强调:我无法想象有人计划这样的更改。 就像.NET团队的人们坐在一起讨论:

启用了ICU的字符串“ \ n \ r \ nTest”是否包含“ \ nTest”? 不,显然不是!

没有人抱怨吗? 没有机会!

这看起来不像是计划或预期的更改,而是看起来像一个非常严重的错误,一个很大的兼容性阻止程序。 因此,新的和移植的.NET应用程序将无法在新的运行时上正常运行,因为它们将无法在字符串内部找到子字符串!

为什么ICU仍然关心行尾? 某些语言环境是否具有自己的特定于语言环境的行结尾?

PS:是的,您可能会争辩说,应该真的总是调用某种与文化无关的IndexOf变体,例如带有序号的。 但是,如果您决定在.NET 5中很难破解它,

另外,我想我们大家都理解,尽管IndexOf始终以特定于文化的方式运行,但仍有大量代码使用IndexOf而没有顺序标志,并且该代码_用于工作_(至少在某些/大多数情况下)。 .NET 5更新后它将停止工作。

问题很明显是IndexOf,它无法在另一个ASCII唯一的字符串中找到一个ASCII唯一的字符串(我不确定在ASCII唯一的字符串上是否有任何与语言环境有关的行为!)。

并非如此ASCII是与语言环境无关的。 以http://userguide.icu-project.org/collat​​ion/concepts链接为例,说明不同文化下ASCII字符的行为如何不同。

For example, in the traditional Spanish sorting order, "ch" is considered a single letter. All words that begin with "ch" sort after all other words beginning with "c", but before words starting with "d".
Other examples of contractions are "ch" in Czech, which sorts after "h", and "lj" and "nj" in Croatian and Latin Serbian, which sort after "l" and "n" respectively.

另外,我想澄清一下,ICU是从Unicode标准中挑选数据和行为的,这是许多专家都深思熟虑的。 @GrabYourPitchforks将发布有关\r\n\案例的更多详细信息。 但是与此同时,您可能熟悉文档https://unicode.org/reports/tr29/,尤其是在提及以下内容的部分中:

Do not break between a CR and LF. Otherwise, break before and after controls.
--
GB3 | CR | × | LF
GB4 | (Control \| CR \| LF) | ÷ |  
GB5 |   | ÷ | (Control \| CR \| LF)

为什么ICU仍然关心行尾? 某些语言环境是否具有自己的特定于语言环境的行结尾?

最后一段对此进行了讨论。

抱歉,但是我不相信这是计划的变更,因此我想强调:我无法想象有人计划进行这种变更。 就像.NET团队的人们坐在一起讨论:
这看起来不像是计划或预期的更改,而是看起来像一个非常严重的错误,一个很大的兼容性阻止程序。 因此,新的和移植的.NET应用程序将无法在新的运行时上正常运行,因为它们将无法在字符串内部找到子字符串!

这是经过精心计划的工作,并且在其中进行了深思。 您可以查看我们很久以前发布并公开共享的问题https://github.com/dotnet/runtime/issues/826
我还要强调一点,全球化行为不仅可以在.NET中更改,而且可以在OS平台和其他平台上随时更改。 这也是我们支持ICU应用程序本地功能以允许应用程序使用特定ICU版本以确保其使用行为不会改变的原因。 另一件事,Windows本身正在推广使用ICU的过程,有一天,大多数用户将使用ICU行为。

像序号一样但是,如果您决定在.NET 5中如此努力地破解它,那么您难道不就让它使用理智的顺序默认值吗? 我认为与目前在.NET 5 RC 2中看到的更改相比,它破坏的应用程序更少。

实际上,我们之前曾尝试过将Silverlight版本中的Ordinal行为设置为默认行为,这导致的问题比这里报告的要多得多。 我们正在寻找更多方法来帮助开发人员在调用IndexOf类时保持意识,并故意提供StringComparison标志来表达意图。 我们也欢迎您提出任何想法。

此外,我认为我们都知道,尽管IndexOf始终以特定于文化的方式运行,但仍有大量的代码在不使用序号的情况下使用IndexOf,并且这些代码可以正常工作(在某些情况下,至少)。 .NET 5更新后它将停止工作。

这就是为什么我们提供了一个配置开关,如果您也愿意的话,可以切换回旧的行为。 看一下System.Globalization.UseNls

@tarekgh ,感谢您的详尽解释!

就目前而言,我认为最好等待有关此特定\r\n行为的详细信息。 我不清楚IndexOf在执行此特定搜索时如何使用“字素簇边界规则”(以及是否应该这样做)。

另外,即使Unicode规范在这里相关(可能很好!),通过阅读https://unicode.org/reports/tr29/ ,我不确定它是否禁止匹配最后的\n 。 在我阅读规范时,它显示CR | × | LF ,其中×意思是“无边界(不允许在此处中断)”。 因此,当中断序列\r\n\n ,仅禁止将“ break”放置在第一个和第二个字符之间,但是应该可以将“ break”放置在第三个字符之前,不是吗? 因此,我将\r\n\n读为两个单独的“字素簇”,即使IndexOf只必须匹配完整的字素簇,并且从不接触部分簇,它仍然应该找到子字符串\nTest在字符串\n\r\nTest

另外,您是否告诉依赖ICU和/或Unicode规范的其他运行时/编程语言在此特定示例中的行为应相同?

我们正在寻找更多方法来帮助开发人员在调用IndexOf类时保持意识,并故意提供StringComparison标志来表达意图。 我们也欢迎您提出任何想法。

_(必要的免责声明:我为JetBrains从事多个项目,包括ReSharper。)_

我最初不想把这一点听起来不像是广告,但是我想这很相关,所以我必须这样做。 默认情况下,ReSharper将针对调用IndexOf的用户代码显示以下警告:
image

_(请注意,在参与此线程之前,我并不了解此特定的ReSharper诊断程序,因此,我并不是为了提出这个论点

因此,我认为在所有其他工具中默认显示此类通知也是一个很好的主意,或者甚至完全不赞成使用此类通知伪造此方法。

@永不

另外,即使Unicode规范在这里相关(可能很好!),通过阅读unicode.org/reports/tr29,我不确定它是否禁止匹配最后一个\ n。 在我阅读规范时,它说的是CR | ×| LF,其中×表示“无边界(在此处不允许中断)”。 因此,当中断一个序列\ r \ n \ n时,仅禁止将“ break”放置在第一个字符与第二个字符之间,但是应该可以将“ break”放置在第三个字符之前,不是吗? 因此,我将\ r \ n \ n理解为两个单独的“字素簇”

那是对的。 \r\n\n将是2个群集,分别为\r\n\n

并且,即使IndexOf只必须匹配完整的字素簇并且绝不接触簇的一部分,它仍应在字符串\ n \ r \ nTest内找到子字符串\ nTest。

那是不对的。 \n\r\nTest将被分成几部分。 \n\r\nTest 。 显然\nTest不能是此字符串的一部分。 考虑一下用符号X替换群集\r\n X 。 现在源字符串将是\nXTest ,其中不包含\nTest

另外,您是否告诉依赖ICU和/或Unicode规范的其他运行时/编程语言在此特定示例中的行为应相同?

如果使用默认的整理强度级别,则答案为是。 ICU可以更改可能影响结果的强度级别。 例如,正如我前面提到的,做类似的事情:

CultureInfo.CurrentCulture.CompareInfo.IndexOf(actual, expected, CompareOptions.IgnoreSymbols)

将更改强度级别并使操作忽略符号(这将更改\n\r ,因为此时将被忽略)

另外,我编写了纯ICU本机C应用程序,并运行了相同的案例:

void SearchString(const char *target, int32_t targetLength, const char *source, int32_t sourceLength)
{
    static UChar usource[100];
    static UChar utarget[100];

    u_charsToUChars(source, usource, sourceLength);
    u_charsToUChars(target, utarget, targetLength);

    UErrorCode status = U_ZERO_ERROR;
    UStringSearch* pSearcher = usearch_open(utarget, targetLength, usource, sourceLength, "en_US", nullptr, &status);
    if (!U_SUCCESS(status))
    {
        printf("usearch_open failed with %d\n", status);
        return;
    }

    int32_t index = usearch_next(pSearcher, &status);
    if (!U_SUCCESS(status))
    {
        printf("usearch_next failed with %d\n", status);
        return;
    }

    printf("search result = %d\n", index);
    usearch_close(pSearcher);
}


int main()
{
    SearchString("\nT", 2, "\r\nT", 3);
    SearchString("\nT", 2, "\n\nT", 3);
}

该应用程序将输出结果:

search result = -1
search result = 1

这与您在.NET中看到的行为相同。

就目前而言,我认为最好等待有关此\ r \ n行为的详细信息。 对我来说,尚不清楚IndexOf在执行此特定搜索时如何使用“字素簇边界规则”(以及是否应该这样做)。

当然,聚类会影响整理操作。 如果您查看http://unicode.org/reports/tr29/tr29-7.html ,显然会指出以下内容:

Grapheme clusters include, but are not limited to, combining character sequences such as (g + °), digraphs such as Slovak “ch”, and sequences with letter modifiers such as kw.簇边界对于排序规则很重要, regular-expressions, and counting “character” positions within text. Word boundaries, line boundaries and sentence boundaries do not occur within a grapheme cluster. In this section, the Unicode Standard provides a determination of where the default grapheme boundaries fall in a string of characters. This algorithm can be tailored for specific locales or other customizations, which is what is done in providing contracting characters in collation tailoring tables.

我不确定是否会有更多详细信息,但是如果他在此处添加更多内容,我将让@GrabYourPitchforks评论。

因此,我认为在所有其他工具中默认显示此类通知也是一个很好的主意,或者甚至完全不赞成使用此类通知伪造此方法。

谢谢!
这也是我们正在考虑的相同方向。

为了我自己,我比较了版本之间的各种重载:

| 方法 netcoreapp3.1 | net5.0 |
| ------------------------------------------------- --------------- | ----------------------------------------------- |
| actual.Contains(expected) | 是的是的
| actual.IndexOf(expected) | 1475 | -1 |
| actual.Contains(expected, StringComparison.CurrentCulture) | 是的错误|
| actual.IndexOf(expected, StringComparison.CurrentCulture) | 1475 | -1 |
| actual.Contains(expected, StringComparison.Ordinal) | 是的是的
| actual.IndexOf(expected, StringComparison.Ordinal) | 1475 | 1475 |
| actual.Contains(expected, StringComparison.InvariantCulture) | 是的错误|
| actual.IndexOf(expected, StringComparison.InvariantCulture) | 1475 | -1 |

请为此提供分析仪。

这似乎是这些更改之一,虽然从长远来看是好的,但是一旦.NET 5启动,就会产生大量的流失。 因此,如果.NET 5和.NET Core 3.1之间这些方法的行为不同,.NET 5调用.NET Standard 2.0库中定义的对象,该对象对传递给其中的string操作,将会发生什么情况?从.NET呼叫站点? 是旧习惯还是新习惯?

@Aaronontheweb的新行为。 我最初是从NUnit3的一个断言中看到的,该断言的目标是netstandard2.0 。 升级后,当我仅更改目标框架时,测试开始失败。

那不是很好-如果要升级,无法控制我要引用的较旧的库。

有多少应用程序无法在单元测试中检测到并投入生产?
.NET团队是否考虑过可能带来的痛苦和问题以及成本?

那不是很好-如果要升级,无法控制我要引用的较旧的库。

好陷阱!
快乐的时间浪费在寻找怪异的虫子上
但是为什么InvariantGlobalization不能解决这个问题呢?

请为此提供分析仪。

是的并且不要忘记F#支持。

有多少应用程序无法在单元测试中检测到

零-因为单元测试无意像.NET BCL本身那样测试外部库/框架。

我认为应该有一个程序集级属性可以控制此行为更改的模式。 至少然后,您可以按装配级别选择加入/退出。 这就意味着.NET标准问题也消失了。

那不是很好-如果要升级,无法控制我要引用的较旧的库。

我不明白为什么你无法控制它。 所有字符串比较都使用ICU或NLS。 如果愿意,可以使用compat开关选择退出ICU,并且所有库都将恢复为旧行为。

您不能依靠全球化数据随时间保持稳定。 Windows团队认为,他们不怕打断依赖稳定全球化数据的人。 全球化功能应该是一个黑匣子; 我认为对于库(尤其是针对.NET Standard的库)来说,它们依赖于这样的实现细节是没有道理的。

我敢肯定,同样有很多人抱怨.NET全球化函数在Windows和Linux上返回不同的结果(也许还有更多的人甚至没有注意到)。 最好统一Windows和其他平台之间的行为,并且任何正确的代码都不应依赖于全球化数据是不可变的。

您是否考虑进行重大更改以使StringComparison.Ordinal成为默认比较策略? 鉴于全球化是如此不稳定,因此至少默认实现使用稳定算法是有道理的。 我敢打赌,使用string.Equals(...)string.Contains(...)等而未通过StringComparison等的人中,有99.9%的人这样做并不是出于处理与语言环境。

编辑:我想我的问题已经得到解答:

实际上,我们之前曾尝试过将Silverlight版本中的Ordinal行为设置为默认行为,这导致的问题比这里报告的要多得多。 我们正在寻找更多方法来帮助开发人员在调用诸如IndexOf之类的代码时保持意识,并故意提供StringComparison标志来表达意图。 我们也欢迎您提出任何想法。

如果愿意,可以使用compat开关选择退出ICU,并且所有库都将恢复为旧行为。

我以图书馆为生,而不是以应用程序为生。 我希望有一种编译时的方式来处理这个问题。

我们所做的大部分工作是InvariantCulture ,根据我以前的理解,这应该是设计不变的。 在这些情况下,.NET 5.0和.NET Core 3.1之间的IndexOf行为似乎也有所不同。

任何分析器如何为现有项目提供帮助?

@petarrepac也是C#

@isaacabraham和VB也是如此;)

我希望有一种编译时的方式来处理这个问题。

@Aaronontheweb,您确实有一种编译时的方式来处理此问题(编译应用程序时)。 您可以将其添加到您的项目中:

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

编辑:这仅适用于使用库的应用程序,不幸的是,编写库时您无法控制它。

从长远来看,Windows团队正在促进向ICU的迁移,因此在某些时候ICU将成为全球化的故事,而我们只是OS库的一个薄薄的包装。

当.NET 5调用在.NET Standard 2.0库中定义的对象,该对象处理从.NET调用站点传入的字符串时,会发生什么情况? 是旧习惯还是新习惯?

将使用新的行为,因为它取决于运行时,.NET Standard只是用于实现运行时的标准。 但是,请注意,这将在Unix和Windows之间带来平台一致性,如果在Unix中运行人们担心的相同库,则会得到ICU结果,因为ICU是支持Unix中的库。

@reflectronic在他的所有观点上都是正确的https://github.com/dotnet/runtime/issues/43736#issuecomment -716681586。

要评论此处提到的@jbogard结果https://github.com/dotnet/runtime/issues/43736#issuecomment -716527590,您可以通过比较Windows和ICU之间的语言行为来总结结果。 顺便说一句,现在Windows上的许多应用程序都使用ICU,并且预计使用量会增加。 此外,这些结果不包括具有.NET Core 3.1及更低版本的Linux。 它将显示.NET 5.0和Linux以前版本之间的一致性。

以前使用的库的要点将被破坏,因为这在Linux上已经被破坏了,所以这不是完全正确的。

您是否会考虑进行重大更改以使StringComparison.Ordinal成为默认比较策略?

我之前提到过,我们之前已经尝试过了,但是投诉量很大,我们无法应用。 我们正在寻找帮助开发人员在调用归类API时有意识地指定字符串比较标志的方法。

我以图书馆为生,而不是以应用程序为生。 我希望有一种编译时的方式来处理这个问题。

是的,某些分析仪可以在这种情况下提供帮助。 通常查看排序规则API调用,并查看哪个未显示使用序数或语言操作的意图。

任何分析器如何为现有项目提供帮助?

分析人员扫描代码并检测未通过标志的归类API的调用,这将有助于查看此类调用并解决检测到的问题。

这也是仅C#的事情。

所做的更改位于.NET运行时内部,该运行时应该是全局的,并且不限于C#。

@tarekgh C#分析器如何在VB或F#代码库中体现自己?

我们所做的大部分工作是InvariantCulture ,根据我以前的理解,这应该是设计不变的。

至关重要的是,在进行此更改之前,实际上不可能在跨平台代码上依赖于此。 即使使用不变文化,NLS和ICU的行为也不总是相同的(此问题已证明)。 就像@tarekgh所说的,这段代码一直以来在Linux上的行为都不同。 既然已经进行了此更改,对于任何最新的Windows安装,“不变文化”的含义实际上应在所有平台上保持一致。

这可能令人惊讶,但是由于用户报告,多年来,我们最终确实发现并修复了许多与平台差异相关的错误,因为我敢肯定,许多其他库作者已经做了很多年了。

我对.NET 5引入新的未知未知种类的新前景并不感到兴奋,并且不仅对我的库,而且对我们的下游依赖性也重新访问了这些修补程序。 这对我们来说是巨大的经济成本,不会为用户带来新的生产率提高。 MSFT中的某人应该在进行此更改的成本/收益讨论中对此加以考虑。

编辑:喜欢,我已经获得了技术优点-是的,谢谢。 请帮助出售这项变更带来的非显而易见的经济利益,而不是成本。 考虑到这个问题的根源,用户为什么仍然应该跨越并升级到.NET 5?

@tarekgh C#分析器如何在VB或F#代码库中体现自己?

我们可以使用单个分析器来覆盖C#和VB(我们力求使分析器在语言上尽可能与语言无关),但是目前我们无法获得F#的分析器覆盖率。

@Aaronontheweb任何使用文化功能并且假设它不会改变的人都已经坏了,即使我们没有执行此ICU更改。 查看Windows团队的博客https://docs.microsoft.com/zh-cn/archive/blogs/shawnste/locale-culture-data-churn ,该博客甚至在讲述NLS行为也是为了改进而改变的情况。 因此,这里的问题不仅仅是转移到ICU,而不仅仅是从应用程序/库的角度抓住任何错误的假设。 升级到5.0与升级到其他以前的版本相同。 应用程序将获得许多新的出色功能,并且需要对应用程序进行测试,因为各个版本之间可能会有一些重大更改。 我并不是在考虑全球化行为的改变是真的在打破,因为我们总是告诉全球化可以在OS和OS版本之间随时更改。 如前所述,我们可以使用config开关选择继续使用NLS升级到5.0。 这将使ICU并不是升级决定中真正考虑的因素。 现在有了ICU,如果决定使用应用程序本地ICU,则这些应用程序将有机会在整个OS上获得更大的一致性,甚至可以更好地控制全球化行为。 我们为应用程序提供了比以前更多的控制权。

相关: https :

(该问题不会跟踪IndexOf _se_。而是,它讨论Compare例程默认为可识别文化的比较器的意外结果。)

任何分析器如何为现有项目提供帮助?

分析人员扫描代码并检测未通过标志的归类API的调用,这将有助于查看此类调用并解决检测到的问题。

我猜分析器必须添加到csproj。
这不会自动发生。 因此,许多现有项目将在没有这些分析器的情况下移至.NET 5。
另外,如前所述,它对F#项目无济于事。

@jeffhandley谢谢,这证实了我已经理解的内容。 因此,必须承认可能的“解决方法”不会帮助F#用户(一个很小的市场,但仍然是MS作为.NET的一等公民而得到MS的完全支持)。 我不懂这啥意思:

所做的更改位于.NET运行时内部,该运行时应该是全局的,并且不限于C#。

我不懂这啥意思:
所做的更改位于.NET运行时内部,该运行时应该是全局的,并且不限于C#。

我的意思是任何使用.NET运行时的语言都将受到影响,而不仅限于C#。

我将再次强烈表达我的意见,即开箱即用的分析仪应该可以发现新世界中的这些陷阱,尤其是如果计划要改变当前行为的话。

我完全理解这样做的技术优点,并不建议您不要进行更改(从长远来看,这似乎是正确的举动)。 我也不是说尚未将其记录为最佳实践。 我要说的是,对于试图提升到.NET 5的开发人员,我们确实需要这样做,这是一个大的,闪烁的错误。开箱即用的开发人员会以其他方式认为这“可行”。

现在,您可以使用@meziantou中的Roslyn分析器库来查找受影响的区域: https

在这种情况下,将抛出MA0074-避免使用隐式的文化敏感方法

image

话虽如此,这确实需要开箱即用,我在这里打开了罗斯林的这个问题: https :

@tarekgh感谢您的澄清。 我的原始观点是,如果您正在寻找适用于所有.NET用户的解决方案,那么分析器就无法解决问题。

我们正在寻找更多方法来帮助开发人员在调用诸如IndexOf之类的代码时保持意识,并故意提供StringComparison标志来表达意图。 我们也欢迎您提出任何想法。

如何弃用旧方法(使用[Obsolete]属性)?

当API表面相同但行为发生变化时,.NET Standard兼容性将如何处理?

只要有充分的记载,对荣誉字素簇的更改就不会困扰我。 一项更改导致字符串方法系列的紧密相关的成员彼此之间的行为不一致。

有人对字符串,字素簇或语言环境的模糊性不屑一顾,可以进行非正式的字符串查询,因为如果str.Contains(无论如何)成功,则无需检查str.IndexOf(无论如何)的结果。 ),因为我们只是被告知它在那儿,因此可以找到。 不必关心哪个第二个参数是默认值,因为默认值肯定会在各个方法中表现出

像这样的不一致产生了一种只能由专家成功使用的语言,并疏远了退出代码阵营的人们。 不要以这种方式提高准入门槛。

我同意@lupestro。 方法行为的不一致非常令人担忧。 如果您将长期坚持使用不同的方法,并且行为前后不一致,将会有很多悲伤。 人们会遇到这种情况,他们会感到被API出卖了,然后他们想知道还有哪些其他的定时炸弹正在爆炸。 .NET的许多采用者都将在此类问题上取消C#。 似乎您应该删除不接受语言环境的重载,或者对方法的默认语言环境进行规范化。 已经有一个Compare and CompareOrdinal,也许需要一个(Last)IndexOf(Any)和(Last)IndexOf(Any)Ordinal。 我不喜欢这种解决方案,但至少它与当前的解决方案保持一致。 也许应该贬低字符串中顺序使用的想法。 如果我必须在快速还是正确之间进行选择,那么我每次都会选择“正确”。 不一致的,非直觉的行为非常令人沮丧。

我看到这个问题已经解决,所以我想它已经决定在.NET 5.0中向前发展。 我知道这很困难,而且文化(如时间)信息会因各种非技术性原因而发生变化。 开发人员需要意识到这一点,但他们还需要依赖于自己的API来保持自我一致性。 @aolszowka至少应指出一个警告(在5.0中),该警告指示有问题...以及更重要的是为什么有问题。 前进很重要,有时这意味着您必须“打破”旧的行为/假设。 这并不意味着需要引入新的不一致之处。 此更改违反了预期以及代码。 如果不可能使方法保持一致,那么我宁愿将CultureInfo强制为显式的(然后可以通过扩展方法解决),而不是因为非直观错误会在代码期间使代码爆炸紧张的开发周期或最糟糕的客户安装。

TLDR:更改需要更改的内容,但不要使API不一致。 如果您要破坏它,请用更好的东西代替它。

我已经使用.NET多年了,使用这些功能时始终默认使用InvariantCulture。 对于除英语以外的其他语言,我一直都知道字符对可以用作其他特定于语言的字母的别名,并且在与CurrentCulture作为默认值进行比较时要进行检查以检查这些对。 例如,当编写ASP.NET代码以根据浏览器发送的用户首选语言来设置线程的CurrentCulture时,这使我很痛苦,而对不使用英语的用户进行比较会使代码以微妙的方式中断。当字符串包含用户输入(语言)和序数文本的混合时。

Unicode字形簇的行为对我来说是一种新的行为,即使我像往常一样使用不变重载,也希望换行和回车符具有序数行为。 在我看来,无论技术上的公义如何,既要做更多工作需要专家知识的行为应该是自愿参加的行为。 也许那艘船是很久以前航行的,但是这种“重大更改”应该像语言更改那样透明地进行,而不必阅读晦涩的博客。 我的同事们几乎不了解C#9.0的新功能,更不用说一些奥秘的ICU规则可能会影响他们今天编写的代码,这些规则有一天可能会移植到.NET 5(或更可能是.NET 6或7)中并在其中进行编译。

我们正在考虑淘汰旧方法。 昨晚我完成了该提案的草案,并将其购物以供内部审核,并将在几小时内将其发布为新期刊。

该草案发布在https://github.com/dotnet/runtime/issues/43956。 它列出了几种可能的前进方式(包括不采取任何措施)的替代方法,并权衡了每种方法的利弊。 请随时在此处留下任何有关拟议行动方案的反馈。

如果您要报告错误,请提出新问题并使用该新问题来描述错误。

如果您对此特定问题有任何评论( "\r\n" vs. "\n" ),请继续在此线程中进行响应。 谢谢!

当我们考虑@GrabYourPitchforks文档中描述的方法时,请重新

我们确实听到您的声音-这里有很多明确的反馈-我们正在努力寻找正确的前进方向,并将不断更新此问题。

只要有充分的记载,对荣誉字素簇的更改就不会困扰我。 一项更改导致字符串方法系列的紧密相关的成员彼此之间的行为不一致。

有人对字符串,字素簇或语言环境的模糊性不屑一顾,可以进行非正式的字符串查询,因为如果str.Contains(无论如何)成功,则无需检查str.IndexOf(无论如何)的结果。 ),因为我们只是被告知它在那儿,因此可以找到。 不必关心哪个第二个参数是默认值,因为默认值肯定会在方法之间表现出_same_行为,从而使他们无需研究所有细微之处就可以使用它们。

像这样的不一致产生了一种只能由专家成功使用的语言,并疏远了退出代码阵营的人们。 不要以这种方式提高准入门槛。

是的,这完全表达了我的担忧。 作为典型的中国开发人员,在我们的应用程序代码中调用与字符串相关的方法时,我们很少显式地放置StringComparisonCultureInfo ,并且它可以正常工作。 我们绝对不会期望IndexOfContains之间会有不同的行为!
.NET 5.0
image
.net核心3.1
image
.net框架
image

我同意@lupestro。 方法行为的不一致非常令人担忧。 如果您将长期坚持使用不同的方法,并且行为前后不一致,将会有很多悲伤。

也许关键点在于这两种方法始终不一致。 它们并没有突然在.NET 5.0中变得不一致。 如果我正确地遵循了这些规定,则IndexOf始终使用当前的区域性比较, Contains始终使用顺序性比较。 授予.NET 5.0会增加更多不一致之处。 但是这里的错误在于允许这种不一致的原始API设计。

如果我正确地遵循了规则,则IndexOf始终使用顺序比较,Contains始终使用当前区域性比较。 授予.NET 5.0会增加更多不一致之处。 但是这里的错误在于允许这种不一致的原始API设计。

没错,但这是相反的, IndexOf(string)使用当前区域性, IndexOf(char)使用序数,而Contains使用序数。

我将简要介绍其他人最近提到的IndexOfContains差异。

IndexOf(string)一直假定_CurrentCulture_比较,而Contains(string)一直假定_Ordinal_比较。 这种差异早在.NET Framework中就已经存在。 它不是.NET 5中引入的新差异。例如,在.NET Framework(使用Windows的NLS工具)上,连字“æ”和两个字符的字符串“ ae”在语言比较器下进行相等比较。 这导致以下差异:

// Sample on .NET Framework, showing Contains & IndexOf returning inconsistent results
Console.WriteLine("encyclopædia".Contains("ae")); // prints 'False'
Console.WriteLine("encyclopædie".IndexOf("ae")); // prints '8' (my machine is set to en-US)

这种差异已经存在了十多年。 它已记录在案,并且对此有指导。 这是设计不当吗? 也许。 我们正在https://github.com/dotnet/runtime/issues/43956讨论如何使生态系统更健康地向前发展。

对于这个特定的问题,我们真正要问自己的是:“鉴于这种差异已经永远存在,在实践中,这两种方法相距多远才可以损害整个生态系统?” 我认为我们仍在尝试确定该阈值应在哪里。 这样的报告非常有用,因为它们使我们深入了解人们在实践中使用这些API以及客户对他们的行为有何期望。 作为框架的管理者,我们不仅需要考虑技术文档,还需要考虑实际应用程序使用这些API的方式。

此评论并不是要捍卫任何特定观点。 我的目的是澄清我所看到的一些误解,并帮助解释我们如何解决该问题。

即使指定了InvariantCulture,ICU版本中\n不匹配的行为是否正确?

image
image

也许,如果我们使用git及其默认设置(autocrlf = true),则以下代码在Linux上显示5,在Windows上显示-1。

using System;

var s = @"hello
world";
Console.WriteLine(s.IndexOf("\n", StringComparison.InvariantCulture));

@ufcpp是,每个ICU是预期的行为,如本线程前面所述。 当两个字符<CR><LF>彼此相邻出现时,出于语言目的,它们被认为是不可破坏的单元。 使用语言比较器(例如_InvariantCulture_)搜索<LF>不会产生匹配,因为它将拆分此牢不可破的单元。

我想与大家分享一个更新:我们决定将ICU保留为5.0 GA的默认设置。 我们将着眼于在使用序数法时使用语言比较来改善偶然性的陷阱,这在https://github.com/dotnet/runtime/issues/43956中进行了跟踪

这是一个非常困难的决定,我们必须权衡对生态系统的兼容性影响和跨平台标准化的驱动力。

如果确定当前的缓解措施不足,我们将保留此问题以考虑进一步缓解\r\n问题。

我还想鼓励人们继续报告由于ICU切换而遇到的问题,即使该行为可能是由已知原因引起的,也不意味着它是“有意设计的”。 我们将继续调查差异并了解根本原因,并确定是否需要将更改驱动到ICU或.NET中以解决它们。

有一个分析器规则,用于始终指定StringComparison。

https://docs.microsoft.com/zh-cn/dotnet/fundamentals/code-analysis/quality-rules/ca1307

我想与大家分享一个更新:我们决定将ICU保留为5.0 GA的默认设置。 我们将研究在按序排列的情况下意外使用语言比较来改善意外情况的陷阱,这在#43956中进行了跟踪。 我们还将联系一些我们确定为受此问题影响的库。 在未来的日子里,我们将在即将发布的5.0版本中共享更多文档,以帮助人们更好地识别有问题的代码并进行修正以避免此问题。

这是一个非常困难的决定,我们必须权衡对生态系统的兼容性影响和跨平台标准化的驱动力。

如果确定当前的缓解措施不足,我们将保留此问题以考虑进一步缓解\r\n问题。

我还想鼓励人们继续报告由于ICU切换而遇到的问题,即使该行为可能是由已知原因引起的,也不意味着它是“有意设计的”。 我们将继续调查差异并了解根本原因,并确定是否需要将更改驱动到ICU或.NET中以解决它们。

我想知道我是否仍然可以控制.NET Standard依赖项。

我怀疑我做不到。 如何确保人们过渡到我不知道的.NET Standard 2.2? 更改API?

这样我就可以知道我得到了预期的行为。

我不确定我们还能如何避免破坏当前的生态系统,因为该生态系统已经存在很多问题。

我很高兴被证明是错误的,请以偏见为由-这会让我放心:)

@rcollina

我想知道我是否仍然可以控制.NET Standard依赖项。

.Net标准库通常被认为是跨平台的。 并且,如果某些库在当今的Unix(使用ICU)的.Net Core 3上可以正常工作,那么几乎可以肯定的是,在Windows(也使用ICU)的.Net 5上它也可以工作。

.NET标准2.2

.Net Standard vNext有效地存在,尽管它被称为“ .Net 5.0”。 (即,如果您正在编写库而又不关心支持较旧的框架,那么今天您将以.Net Standard 2.1为目标。一个月之内,您将以.Net 5.0为目标。)

@svick我明白了。 我相信我已经了解.NET Standard的工作原理。 我知道.NET 5确实是新的.NET标准。

抱歉,我仍然不确定当我引用依赖于IndexOf和Contains之间预先存在的行为不一致的.NET Standard 2.1库时会发生什么。

这里的变化是带外,ICU与NLS。 这种变化扩大了我们已经存在的差异,并打破了预期。
没有任何信息将此信息编码为库。

我想不理解所有的含义,但是如果没有通向新常态的无缝入门途径,我就无法摆脱我们在技术上正确的感觉。 迫切需要。

正如其他人提到的那样,大多数人甚至都不知道新的语言功能,更不用说地震变化了,例如我们最好的社区成员随机发现的变化。 我们可以承受的机会是什么?

我想知道我是否仍然可以控制.NET Standard依赖项。

这里的变化是带外,ICU与NLS。 这种变化扩大了我们已经存在的差异,并打破了预期。

不,不是。 这里要强调的是,ICU总是在Unix上使用过。 .NET标准库应该设计为可移植的,并且以前在Linux .NET Core 3.x上工作的所有内容都可以在.NET 5中工作。

我们所做的大部分工作是InvariantCulture,根据我以前的理解,该变量应该设计不变。

不对。 InvariantCulture仅应忽略用户的语言设置。 它仍然可以随着unicode规范或全球化库等的更新而改变。

.NET团队是否考虑过可能带来的痛苦和问题以及成本?

像这样的言论让我感到无休止。 任何突然因此更改而中断的代码都是不正确的。 如果.NET团队必须保留不正确或依赖于实现细节的用户代码的行为,平台应如何前进? 并不是说他们没有提供兼容性开关。 从.NET Framework中分离出来的.NET Core的很大一部分原因是通过并排安装和应用程序本地运行时部署等功能来解决此问题。 如果因为这个原因而无法移至.NET 5,请不要移至.NET 5。

我对.NET 5引入新的未知未知种类的新前景并不感到兴奋,并且不仅对我的库,而且对我们的下游依赖性也重新访问了这些修补程序。

如果您声称自己已经解决了所有平台差异错误,那么您就不必担心。

.NET团队是否考虑过可能带来的痛苦和问题以及成本?

像这样的言论让我感到无休止。

数以百万计的项目正在.NET上运行,并且字符串操作是非常频繁的操作。
与验证将要迁移到.NET 5/6的所有现有代码所需的工作相比,.NET团队修复/更改此工作所花费的精力很小。

因此,询问解决此问题的“计划”是很公平的。
有什么计划吗?
估计此更改的影响了吗?
是所有项目的0.001%吗? 是75%吗?
我们不知道还有哪些其他类似的变化?

也许这只影响少数项目。
但是,估计吗?

顺便说一句,我有足够的理由来打破变化。 但是,我们还需要一个不太冒险的迁移路径。

@petarrepac不要误会我的意思,我理解。 但正如在该线程中多次指出的那样:

  1. 有一个计划,它将提供一个运行时配置开关。
  2. 声称被破坏的行为是.NET在所有非Windows平台上的现有行为。
  3. 这只应影响在需要按序执行的区域性敏感代码的代码。

考虑到最后两点,可以合理地假设这会影响到很小比例的项目。

100%可以问这个问题,但是像我所引用的那样写评论的人通常只是假设在试图理解变更背后的整体之前没有考虑和撰写任何评论。

大家好。 我们想简要概述一下此问题发生时我们所采取的操作,并最终说明了为什么我们决定在Windows 10 May 2019 Update或更高版本上将默认设置保留为.NET 5.0的ICU。

当问题打开时,由于Contains(string)之间的不一致,即OrdinalIndexOf(string)之间,我们可能会对客户造成潜在的影响和痛苦,我们进行了一些内部讨论。 Span<char>ReadOnlySpan<char>之上进行操作时,其默认值为Ordinal ReadOnlySpan<char> 。 因此,在讨论了这个问题之后,我们开始对可能受到影响的NuGet软件包进行分析,并收集数据以获得清晰的图像。 这是我们的发现:

  • 在传递给IndexOf,LastIndexOf,EndsWith,StartsWith,Compare和CompareTo的“最常用的字符串文字”上,“ \ n”是#30。
  • 1%的String.EndsWith呼叫站点带有以\ n开头的搜索字符串。 这些被测试字符串包含“ windows样式的行尾”的callsite都将被破坏。
  • NuGet.org上托管有2040个软件包ID,其中一个版本包含带有风险呼叫站点的程序集。
  • 这些调用场所中的绝大多数是EndsWith和IndexOf,这与以下假设相符:该模式经常用于幼稚的换行算法。

在这些具有高风险呼叫站点的2040个软件包中,只有539个支持.NET Standard或.NET Core的某些版本,因此,NuGet.org中列出的0.54%的软件包可能会受到破坏。

我们查看了539个可能受影响的程序包ID列表中的程序包,以了解对这些程序包的实际影响。 我们查看了前70名(按下载数量计),其中20名未公开最新版本的模式,而那些公开了该模式的人仅查看了拥有许可证的32个:

  • 14个没有bug
  • 13个可能被破坏
  • 5个不确定(由于针对不同的换行模式或其他缓解措施的防御性编码,没有明确的中断迹象)。

因此,这意味着,从下载的前70个软件包中,只有18%受到了潜在影响。

这些百分比是堆叠的,并不与NuGet.org上的软件包总数229,536相对。 因此,如果我们使用NuGet.org中的软件包总数和下载总数,我们将查看229,536个中的539个潜在受影响的软件包,即0.24%。

尽管对我们来说分析库非常好,但nuget仅代表其中的一小部分C#代码。 即使有人拥有代码,a)错误可能也不容易被发现,b)他们可能实际上不再具有源代码。

但是,这是一个很好的数据来源,可以得出结论,尽管这可能是行为上的非常显着的变化,但在读取可能包含Windows Line Ends(可能并不常见)的输入时,Unix上已经发生了这种中断。

在.NET Core和.NET 5+中,我们正在努力实现跨操作系统的一致性,并且鉴于此更改的影响,感觉上应该做对。 我们确实关心兼容性,因此正在为人们提供一个兼容的运行时开关,使他们能够恢复到传统行为。

同样,从可以检查的软件包得出的结论(鉴于Unix上的行为已经有所不同),我们确实看到了针对此问题的许多防御性编程,以减轻操作系统之间的潜在中断。

除此之外,全球化可以随时更改,因为我们是整个OS的精简包装,因此目前看来,在我们支持的所有OS上都使用相同的包装是正确的选择。

在此过程中,我们通过实际示例,roslyn分析器规则以及受影响的代码如何缓解这种情况来改进了文档。

感谢您提供所有宝贵的反馈意见,因为它总是可以带我们到一个更好的地方,我们将尽力改善.NET 6的这种体验,如下所述: https :

由于我们了解由于Unix和Windows之间的行尾之间的差异而可能造成的痛苦,因此我们将这个问题保持开放状态,我们将研究减轻.NET 5.0 \r\n情况的一种可行方法。 .x,它应该是服务版本的一部分。

char和string也有区别:

Console.WriteLine("com/test/test/test/a/b/ʹ$ʹ".IndexOf("$"));
Console.WriteLine("com/test/test/test/a/b/ʹ$ʹ".IndexOf('$'));
-1
24

@mattleibow在使用字符搜索时,将执行顺序搜索。 该文档https://docs.microsoft.com/zh-cn/dotnet/api/system.string.indexof?view=net-5.0#System_String_IndexOf_System_Char_表示This method performs an ordinal (culture-insensitive) search 。 如果使用ordinal选项进行字符串搜索,您将获得与字符相同的结果。

C# Console.WriteLine("com/test/test/test/a/b/ʹ$ʹ".IndexOf("$", StringComparison.Ordinal));

〜似乎CA1307仅在indexof(char)上触发,而不在indexof(string)上触发。 string版本有规则吗? 这似乎更为重要,因为默认的char自动使用ordinal,而重大更改并没有真正影响到此,而string的行为已更改,您需要指定ordinal才能恢复行为。有些情况。

〜如何检测indexof(string) ?〜

找到它,这是CA1310的规则。 对于https://docs.microsoft.com/zh-CN/dotnet/standard/globalization-localization/globalization-icu#use -nls-instead-of-icu,我们的文档是错误的,

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

jamesqo picture jamesqo  ·  3评论

Timovzl picture Timovzl  ·  3评论

bencz picture bencz  ·  3评论

omariom picture omariom  ·  3评论

yahorsi picture yahorsi  ·  3评论