String.Equals vs String.Compare vs“==”in Action。需要说明

时间:2015-06-17 07:31:00

标签: c# .net string string-comparison

以下是控制台应用程序的代码段 -

class MyClass
{        
   public int GetDay(string data22)
    {
        int returnValue = 0;

        if (string.Compare(data22,"THURSDAY") == 0) // true
        {
            returnValue = (int)DayOfWeek.Thursday;
        }

        if (data22 == "THURSDAY") //false
        {
            returnValue = (int)DayOfWeek.Thursday;
        }

        if (string.Equals(data22, "THURSDAY"))//false
        {
            returnValue = (int)DayOfWeek.Thursday;
        }
        return returnValue;
    }
}

class Program
{
    static void Main(string[] args)
    {
        string ExecutionDay = "‎THURSDAY";
        MyClass obj1 = new MyClass();
        int MyDays = obj1.GetDay(ExecutionDay);
    }
}

问题是 - 为什么第一次比较(string.compare)有效,而另外两种比较方法在这个特殊情况下不起作用?

4 个答案:

答案 0 :(得分:13)

  

为什么第一个比较(string.compare)和另外两个比较   比较方法在本特定情况下不起作用

您的代码中有不可见的字符(特别是Left-to-Right mark(感谢@Matthewatson))。您可以使用任何十六进制编辑器查看它们:

enter image description here

string.Compare覆盖了这一点,而string.Equals则没有。您可以在the docs中看到它:

  

来电者注意事项:

     

字符集包括可忽略的字符。该   比较(String,String)方法时不考虑这样的字符   它执行文化敏感的比较。例如,如果   以下代码在.NET Framework 4或更高版本上运行,a   “动物”与“动物”的文化敏感比较(使用柔软的   连字符或U + 00AD)表示两个字符串是等效的。

答案 1 :(得分:3)

ExecutionDay字符串包含不可见的字符,否则所有检查都将为真

以下行返回不同的长度,分别为9和8

        Console.WriteLine(ExecutionDay.Length);
        Console.WriteLine("THURSDAY".Length);

答案 2 :(得分:1)

有一个"隐形"

开头的字符
string ExecutionDay = "‎THURSDAY";

它是LEFT-TO-RIGHT MARK。您可以查看:

int len = ExecutionDay.Length; // 9 instead of 8

char ch = ExecutionDay[0]; // 8206

答案 3 :(得分:0)

简而言之,CompareTo依赖于文化。例如ß (s sharp from German)

Console.WriteLine("ß Compare ss 1: " + ("ß".CompareTo("ss") == 0));
Console.WriteLine("ß Compare ss 2: " + (String.Compare("ß", "ss", StringComparison.Ordinal) == 0));
Console.WriteLine("ß equals ss: " + "ß".Equals("ss"));
Console.WriteLine("ß == ss: " + ("ß" == "ss"));

会打印出来

ß Compare ss 1: True
ß Compare ss 2: False
ß equals ss: False
ß == ss: False

在您的情况下,您的字符串看起来相同,但不同。通常我觉得看到差异很有帮助,可以通过以下方式完成:

Console.WriteLine(
  string.Join(", ", 
    ExecutionDay
      .ToCharArray()
      .Select(o =((int)o).ToString(CultureInfo.InvariantCulture))
      .AsEnumerable()
  )
);

产生字符数代码列表:

8206, 84, 72, 85, 82, 83, 68, 65, 89

unicode中的字符8206left-to-right mark

==比较

这将仅比较值,如果它是值类型或基元。除此之外,它应该用作REFERENCE比较。在C#中,类型字符串是特殊的,并且以下2个断言中的两个都将产生 true

string ss = getinput();//"SS"
assertTrue("SS"=="SS");
assertTrue( ss =="SS");

在Java中,首先会返回true beacuse JIT运行时优化器,它从代码中收集所有唯一字符串并创建一个使用的表。第二个为false,因为字符串只是不可变字符数组,如果用户输入新内存空间,则参考比较返回 false

C# Guidelines for Implementing Equals and the Equality Operator (==)

等于比较

== 不同,Equals方法只是在System.Object中定义的虚拟方法,并且被选择这样做的任何类重写。因此,将使用被覆盖的版本,如果是字符串类型,这意味着将完成内容比较。

  

覆盖Equals(对象)时请遵循以下准则:

     
      
  • 实现IComparable的类型必须覆盖Equals(Object)。
  •   
  • 重写Equals(Object)的类型也必须覆盖GetHashCode;否则,哈希表可能无法正常工作。
  •   
  • 您应该考虑实现IEquatable接口以支持强类型测试以获得相等性。你的IEquatable.Equals   实现应该返回与Equals一致的结果。
  •   
  • 如果您的编程语言支持运算符重载,并且您为给定类型重载了相等运算符,则还必须   重写Equals(Object)方法以返回与结果相同的结果   平等运算符。这有助于确保使用的类库代码   Equals(例如ArrayList和Hashtable)的行为方式是   与applicat使用等于运算符的方式一致
  •   

C# Implementing the Equals Method

比较

  

注意

     

CompareTo 方法主要是为   用于排序或字母顺序操作。它不应该在使用时使用   方法调用的主要目的是确定是否两个   字符串是等价的。确定两个字符串是否为   相当于,调用Equals方法。

此方法使用当前文化执行单词(区分大小写和文化敏感)比较。有关word,string和ordinal排序的更多信息,请参阅System.Globalization.CompareOptions。

来源:Manual