InvariantCulture和Ordinal字符串比较之间的区别

Kap*_*pil 518 .net c# string-comparison ordinal

比较c#中的两个字符串是否相等,InvariantCulture和Ordinal比较之间有什么区别?

Jar*_*ger 284

InvariantCulture的

使用"标准"字符排序集(a,b,c,......等).这与某些特定区域设置形成对比,这些区域设置可以按不同顺序对字符进行排序("a-with-acute"可以在'a' 之前之后,具体取决于区域设置,依此类推).

序数词

另一方面,看起来纯粹是表示字符的原始字节的值.


http://msdn.microsoft.com/en-us/library/e6883c06.aspx上有一个很好的示例,它显示了各种StringComparison值的结果.一直到最后,它显示(摘录):

StringComparison.InvariantCulture:
LATIN SMALL LETTER I (U+0069) is less than LATIN SMALL LETTER DOTLESS I (U+0131)
LATIN SMALL LETTER I (U+0069) is less than LATIN CAPITAL LETTER I (U+0049)
LATIN SMALL LETTER DOTLESS I (U+0131) is greater than LATIN CAPITAL LETTER I (U+0049)

StringComparison.Ordinal:
LATIN SMALL LETTER I (U+0069) is less than LATIN SMALL LETTER DOTLESS I (U+0131)
LATIN SMALL LETTER I (U+0069) is greater than LATIN CAPITAL LETTER I (U+0049)
LATIN SMALL LETTER DOTLESS I (U+0131) is greater than LATIN CAPITAL LETTER I (U+0049)
Run Code Online (Sandbox Code Playgroud)

您可以看到InvariantCulture的收益率(U + 0069,U + 0049,U + 00131),序数收益率(U + 0049,U + 0069,U + 00131).

  • 我觉得这是有用的信息,但实际上并没有回答这个问题.在确定两个字符串的*Equality*时,是否有任何理由使用InvarintCulture而不是Ordinal?似乎InvariantCulture将用于*Sort*字符串,而Ordinal应该用于*Equality*检查(我们不关心重音 - a来自a之前或之后,它只是不同).虽然,我自己有点不确定这一点. (131认同)
  • 序数比较查看*代码点*,而不是字节. (24认同)
  • 序数要快得多 (23认同)
  • 请参阅http://msdn.microsoft.com/en-us/library/ms230117%28v=vs.90%29.aspx并注意建议使用字符串规范化和序数比较. (18认同)
  • 已发布了良好的性能测试结果[C#String Comparision Tests](http://rhale78.wordpress.com/2011/05/16/string-equality-and-performance-in-c/),它告诉每个不同的性能字符串比较方法和他们的时间. (9认同)
  • @Joey看到.NET对所有字符串使用相同的编码(UTF-16),代码点和字节之间的区别是什么?另外文档状态*"在方法调用中指定StringComparison.Ordinal或StringComparison.OrdinalIgnoreCase值表示忽略自然语言的特征的非语言比较.使用这些StringComparison值调用的方法基于简单的字符串操作决策字节比较"*http://msdn.microsoft.com/en-us/library/dd465121(v=vs.100).aspx (2认同)
  • 关于上面MPavlak的“不确定”评论(此时)有106个赞成票,这表明在相等性检查方面,序数和不变式之间没有区别,实际上是有区别的。即使是由于字符扩展而导致的相等性检查,它们也有所不同,这在同一线程的另一个答案中得到了证明:/sf/answers/1405965361/ (2认同)
  • 就这个答案而言,它没有回答问题。 (2认同)

Ven*_*kov 229

例如,它确实很重要 - 有一种叫做角色扩展的东西

var s1 = "Strasse";
var s2 = "Straße";

s1.Equals(s2, StringComparison.Ordinal);           //false
s1.Equals(s2, StringComparison.InvariantCulture);  //true
Run Code Online (Sandbox Code Playgroud)

随着InvariantCultureß角色扩展到ss.

  • 这不太正确@Peter,你不能在德语中互换使用`ß`和`s`(我是母语人士).有些情况下两者都是合法的(但通常有一个是过时的/不推荐的),并且有些情况下只允许使用一种表格. (18认同)
  • 这个简单的例子清楚地说明了两种比较之间的区别.我想我现在正在接受这个. (4认同)
  • 请注意,至少在 .NET 5 中,两个比较都返回 false。 (4认同)
  • 请参阅此处的相关文章:[在 .NET 5+ 上比较字符串时的行为变化](https://learn.microsoft.com/en-us/dotnet/standard/base-types/string-comparison-net-5-plus) 。 (4认同)
  • 对于那些不知道"ß"的人,应该注意到至少在德语中的"ß"等于双倍,来源:https://en.wikipedia.org/wiki/%C3%9F (3认同)
  • 不得不尝试一下:https://ideone.com/j8Dv这么酷!还有一点德语课.想知道ß和ss之间有什么区别... (3认同)
  • 另外,在 InvariantCulture 中,“Æ”总是扩展为“AE” (2认同)

Dar*_*usz 97

指向在.NET Framework中使用字符串的最佳实践:

  • 使用StringComparison.OrdinalStringComparison.OrdinalIgnoreCase进行比较作为与文化无关的字符串匹配的安全默认值.
  • 使用比较StringComparison.OrdinalStringComparison.OrdinalIgnoreCase获得更好的性能.
  • 基于比较在语言上无关的时间(例如,符号),使用非语言StringComparison.OrdinalStringComparison.OrdinalIgnoreCase值而不是字符串操作CultureInfo.InvariantCulture.

最后:

  • StringComparison.InvariantCulture在大多数情况下,不要使用基于字符串的操作.少数例外情况之一是当你坚持语言上有意义但文化上不可知的数据时.


Rob*_*ker 56

另一个方便的区别(在英语中,重音不常见)是InvariantCulture比较首先按不区分大小写比较整个字符串,然后在必要时(和请求)在首先仅对不同的字母进行比较之后进行区分.(当然,您也可以进行不区分大小写的比较,这不会因情况而区分.) 更正:重音字母被认为是相同字母的另一种风格,字符串首先忽略重音,然后在一般字母全部匹配的情况下进行比较(与不同情况一样,除非在不区分大小写的比较中最终忽略).这将其他相同单词的重音版本分组,而不是在第一个重音差异处完全分开.这是您通常在字典中找到的排序顺序,大写单词出现在它们的小写等价物旁边,重音字母靠近相应的非重音字母.

序数比较严格地比较数字字符值,在第一个差异处停止.这种大写字母与小写字母(以及可能与这些字母分开的重音字母)完全分开,因此大写单词在其小写等价物附近排序.

InvariantCulture还认为大写字母大于小写字母,而Ordinal认为大写字母小于小写字母(从计算机使用小写字母之前的旧日期中保留ASCII,大写字母首先被分配,因此其值低于小写字母后来添加).

例如,Ordinal: "0" < "9" < "A" < "Ab" < "Z" < "a" < "aB" < "ab" < "z" < "Á" < "Áb" < "á" < "áb"

并通过InvariantCulture: "0" < "9" < "a" < "A" < "á" < "Á" < "ab" < "aB" < "Ab" < "áb" < "Áb" < "z" < "Z"


Eug*_*sky 29

虽然问题是关于平等,但为了快速视觉参考,这里使用一些文化排序的一些字符串的顺序说明了那里的一些特质.

Ordinal          0 9 A Ab a aB aa ab ss Ä Äb ß ä äb ? ? ? ? ? ?
IgnoreCase       0 9 a A aa ab Ab aB ss ä Ä äb Äb ß ? ? ? ? ? ?
--------------------------------------------------------------------
InvariantCulture 0 9 a A ? ä Ä aa ab aB Ab äb Äb ss ß ? ? ? ? ?
IgnoreCase       0 9 A a ? Ä ä aa Ab aB ab Äb äb ß ss ? ? ? ? ?
--------------------------------------------------------------------
da-DK            0 9 a A ? ab aB Ab ss ß ä Ä äb Äb aa ? ? ? ? ?
IgnoreCase       0 9 A a ? Ab aB ab ß ss Ä ä Äb äb aa ? ? ? ? ?
--------------------------------------------------------------------
de-DE            0 9 a A ? ä Ä aa ab aB Ab äb Äb ß ss ? ? ? ? ?
IgnoreCase       0 9 A a ? Ä ä aa Ab aB ab Äb äb ss ß ? ? ? ? ?
--------------------------------------------------------------------
en-US            0 9 a A ? ä Ä aa ab aB Ab äb Äb ß ss ? ? ? ? ?
IgnoreCase       0 9 A a ? Ä ä aa Ab aB ab Äb äb ss ß ? ? ? ? ?
--------------------------------------------------------------------
ja-JP            0 9 a A ? ä Ä aa ab aB Ab äb Äb ß ss ? ? ? ? ?
IgnoreCase       0 9 A a ? Ä ä aa Ab aB ab Äb äb ss ß ? ? ? ? ?
Run Code Online (Sandbox Code Playgroud)

观察:

  • de-DE,ja-JPen-US以相同的方式排序
  • Invariant只有ssß上述三种文化不同并且不同
  • da-DK 完全不同的排序
  • IgnoreCase所有抽样文化标志事项

用于生成上表的代码:

var l = new List<string>
    { "0", "9", "A", "Ab", "a", "aB", "aa", "ab", "ss", "ß",
      "Ä", "Äb", "ä", "äb", "?", "?", "?", "?", "?", "?" };

foreach (var comparer in new[]
{
    StringComparer.Ordinal,
    StringComparer.OrdinalIgnoreCase,
    StringComparer.InvariantCulture,
    StringComparer.InvariantCultureIgnoreCase,
    StringComparer.Create(new CultureInfo("da-DK"), false),
    StringComparer.Create(new CultureInfo("da-DK"), true),
    StringComparer.Create(new CultureInfo("de-DE"), false),
    StringComparer.Create(new CultureInfo("de-DE"), true),
    StringComparer.Create(new CultureInfo("en-US"), false),
    StringComparer.Create(new CultureInfo("en-US"), true),
    StringComparer.Create(new CultureInfo("ja-JP"), false),
    StringComparer.Create(new CultureInfo("ja-JP"), true),
})
{
    l.Sort(comparer);
    Console.WriteLine(string.Join(" ", l));
}
Run Code Online (Sandbox Code Playgroud)

  • 嗯 - 好的,很高兴您进行了这项研究并发布了您的发现,尽管我不确定您的观点是什么。无论如何,丹麦人可能不是“最重要的文化”之一(尽管 500 万丹麦人实际上相当喜欢他们的文化),但是如果您将“aa”作为附加测试字符串放入,而将“da-DK”放入作为一个额外的测试文化,你会看到一些有趣的结果。 (2认同)
  • @RenniePet 谢谢你。我添加了丹麦语,因为它与使用的其他 3 种文化有很大不同。(由于表示讽刺的表情符号在英语阅读网络中似乎并不像我想象的那样被很好地理解,因此我删除了“最重要的文化”评论。毕竟,BCL 没有提供“文化比较器”功能我们可以用它来验证。对于这个表,“丹麦”文化(信息)非常重要。) (2认同)

Dan*_*anH 26

不变量是一种语言上适当的比较类型.
序数是二元类型的比较.(更快)
参见http://www.siao2.com/2004/12/29/344136.aspx


Dwe*_*dit 5

这是一个示例,其中使用InvariantCultureIgnoreCase和OrdinalIgnoreCase进行的字符串相等比较不会给出相同的结果:

string str = "\xC4"; //A with umlaut, Ä
string A = str.Normalize(NormalizationForm.FormC);
//Length is 1, this will contain the single A with umlaut character (Ä)
string B = str.Normalize(NormalizationForm.FormD);
//Length is 2, this will contain an uppercase A followed by an umlaut combining character
bool equals1 = A.Equals(B, StringComparison.OrdinalIgnoreCase);
bool equals2 = A.Equals(B, StringComparison.InvariantCultureIgnoreCase);
Run Code Online (Sandbox Code Playgroud)

如果运行此命令,则equals1将为false,equals2将为true。