【问题标题】:Understanding String Comparison behaviour了解字符串比较行为
【发布时间】:2017-11-15 09:08:45
【问题描述】:

我需要将一些字符串比较从 vb 转换为 c#。 vb 代码使用 > 和

[TestMethod]
public void TestMethod2()
{
    string originalCulture = CultureInfo.CurrentCulture.Name; // en-GB

    var a = "d".CompareTo("t");  // returns -1
    var b = "T".CompareTo("t");  // returns 1

    Assert.IsTrue(a < 0, "Case 1");
    Assert.IsTrue(b <= 0, "Case 2");
}

有人可以解释为什么 b 返回 1。我目前的理解是,如果它区分大小写,那么“T”应该在排序顺序中位于“t”之前,即 -1。如果不区分大小写,则相同,即 0

(仅供参考.Net Framework 4.5.2)

很多感谢

【问题讨论】:

  • 能把VB代码也显示一下吗?
  • 为什么你特别希望大写在小写之前? (诚​​然,如果你使用 ordinal 比较,它确实如此。)
  • 来自msdn.microsoft.com/en-us/library/35f0x18w(v=vs.110).aspx "此方法使用当前区域性执行单词(区分大小写和区域性)比较"。然后建议阅读msdn.microsoft.com/en-us/library/84787k22(v=vs.110).aspx 以获取更多信息,其中指出“比较使用当前文化来获取特定于文化的信息,例如大小写规则”。所以它可能取决于你的默认文化是什么以及它的规则是什么。您可以使用此方法覆盖默认值 msdn.microsoft.com/en-us/library/e6883c06(v=vs.110).aspx
  • 使用返回-16的int a = string.Compare("d", "t", StringComparison.Ordinal)和返回-32的int b = string.Compare("T", "t", StringComparison.Ordinal);。如果您不指定StringComparison,则使用CurrentCulture
  • 是的,但是您进行的比较是一种文化比较。如果您要求进行序数比较(例如string.Compare("T", "t", StringComparison.Ordinal)),那么会给出不同的结果。

标签: c#


【解决方案1】:

小写在大写之前。 这对于 en-GB 和 InvariantCulture 都是如此。

如果你想要类似 ASCII 的行为,你应该指定额外的 CompareOptions.Ordinal 参数

请参阅以下内容:

repl.it 上的示例代码:

using System;
using System.Globalization;
using System.Collections.Generic;

class MainClass
{
    public static void Main(string[] args)
    {

        //All the following case sensitive comparisons puts d before D
        Console.WriteLine("D".CompareTo("d"));
        Console.WriteLine(String.Compare("D", "d", false));
        Console.WriteLine(String.Compare("D", "d", false, CultureInfo.InvariantCulture));

        //All the following case sensitive comparisons puts capital D before small letter d
        Console.WriteLine(String.Compare("D", "d", CultureInfo.InvariantCulture, CompareOptions.Ordinal));

        //The following is case insensitive
        Console.WriteLine(String.Compare("D", "d", true));

        //The default string ordering in my case is d before D
        var list = new List<string>(new[] { "D", "d" });
        list.Sort();
        foreach (var s in list)
        {
            Console.WriteLine(s);
        }
    }
}

//Results on repl.it
//Mono C# compiler version 4.0.4.0
//   
//1
//1
//1
//-32
//0
//d
//D

祝你好运

艾尔

【讨论】:

    【解决方案2】:

    排序顺序基于二进制比较或文本比较,具体取决于选项比较的设置。 - https://docs.microsoft.com/en-us/dotnet/visual-basic/programming-guide/language-features/operators-and-expressions/comparison-operators

    可以看出,有两种比较字符串的方式...那么,哪种方式是默认的?

    Option Compare 语句指定字符串比较方法(二进制或文本)。默认文本比较方法是二进制。 - https://docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/statements/option-compare-statement

    可以看出二进制是默认比较。这意味着任何大写字母都将被视为小于任何小写字母。即"T"&lt;"t" 是真的,但不直观地"Z"&lt;"t""A"&lt;"t" 也都是真的。

    因此,VB 很可能实际上并没有按照您的预期进行,而是使用了相当于将 StringComparer.Ordinal 传递给 String.Compare 方法的比较。请注意,当人们比较字符串时,我所说的并不是您所期望的那样,他们通常会期望“正常”的文本比较。

    【讨论】:

    • “如果你真的想复制这种行为,那么你可以在比较之前将它们转换为 int,但对于更长的字符串,复制会更加棘手。” - 不,要进行序数比较,您使用StringComparison.Ordinal,假设您对“二进制”表示为“UTF-16”感到满意。
    • @JonSkeet:是的,我只是在编辑它。我有片刻。 ;-)
    【解决方案3】:

    如果没有指定 CompareTo(strA, strB) 使用

    CultureInfo.CurrentCulture.CompareInfo.Compare(strA, strB, CompareOptions.None);
    

    对于 en-GB,小写字母小于大写字母。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-12
      • 1970-01-01
      相关资源
      最近更新 更多