How to correctly compare strings in C #: Equals or == ?

 string str1 = "s"; string str2 = "s"; Console.WriteLine("eq: " + str1.Equals(str2)); Console.WriteLine("==: " + (str1 == str2)); 

In both cases, the result is True , although the String is a class and the == operator should compare the links.

IlDasm showed that 2 variables are created and compared according to the Equals and == (op_Equality)

  IL_0000: nop IL_0001: ldstr "s" IL_0006: stloc.0 IL_0007: ldstr "s" IL_000c: stloc.1 IL_000d: ldstr "eq: " IL_0012: ldloc.0 IL_0013: ldloc.1 IL_0014: callvirt instance bool [mscorlib]System.String::Equals(string) IL_0019: box [mscorlib]System.Boolean IL_001e: call string [mscorlib]System.String::Concat(object, object) IL_0023: call void [mscorlib]System.Console::WriteLine(string) IL_0028: nop IL_0029: ldstr "==: " IL_002e: ldloc.0 IL_002f: ldloc.1 IL_0030: call bool [mscorlib]System.String::op_Equality(string, string) IL_0035: box [mscorlib]System.Boolean IL_003a: call string [mscorlib]System.String::Concat(object, object) 
  • 2
    The == operator compares only links (and thus j, sxyj is useless) only in Java. In C #, unlike Java, there is an operator overload. - VladD

3 answers 3

In C #, it is correct to compare strings with both == and Equals . But it would be preferable to compare with == .

Why is that?

The Equals method implies a comparison of the values ​​of objects of the reference type, it is declared as virtual and it is overloaded for strings and compares them, as expected, by value. In your classes you have to give your implementation for it. Otherwise, it will behave like ReferenceEquals and for links that point to more than one object it will give false , even though they will be equal in value.

The == operator for strings represents its implementation, which is different from the standard for all other objects of reference type. If the compared links are of the type System.String , then it will first compare whether the references point to the same object and if not, it will compare two references of the type System.String by value.

But a small note , if we compare an object of type System.String ( string ) with an object of type System.Object (object) that points to a string, they will be compared by value.

Example:

 string str = "str"; object obj = "str"; bool result = str.Equals(obj); 

result will be equal to true , since obj will be obj to the string type, because we called the Equals method on the string (an object of the string type).

But if we compare an object of type System.Object (object) that points to a string, with an object of type System.String ( string ) they will be compared by reference.

Example:

 string str = "str"; object obj = "str"; bool result = obj.Equals(str); 

result will be equal to false , since str will be cast to type object , because we called the Equals method on an object of type object .

Therefore, in this case, it is important to cast object to type string

  • one
    String.Equals (object) attempts to cast object to a string, and compare by value. But on the contrary - no. - PashaPash
  • @PashaPash, yes, right remark, I'll correct it now) - Umed

Operator == not required to compare only links. In C #, operators can be redefined, and it is naturally redefined for a set of types.

Link comparison is simply the default behavior for types for which the == operator is not overridden.

For the types for which the operator == is redefined, Equals will most likely be redefined, and the result for both comparison methods will most likely be the same (if not, then the author simply made a mistake when designing the type).

Here is the implementation of the == for the String from the reference source :

 public static bool operator == (String a, String b) { return String.Equals(a, b); } public static bool Equals(String a, String b) { if ((Object)a==(Object)b) { return true; } if ((Object)a==null || (Object)b==null) { return false; } if (a.Length != b.Length) return false; return EqualsHelper(a, b); } 

But the implementation of non-static Equals from the same:

 public override bool Equals(Object obj) { if (this == null) //this is necessary to guard against reverse-pinvokes and throw new NullReferenceException(); //other callers who do not use the callvirt instruction String str = obj as String; if (str == null) return false; if (Object.ReferenceEquals(this, obj)) return true; if (this.Length != str.Length) return false; return EqualsHelper(this, str); } 

They differ only in a small adjustment for non-static. Both compare references and check the case of null != null , then compare the length for inequality, and only then the value.

  • Thanks for the reference source :) - Vadim Prokopchuk

In C #, both the == operator and the Equals method are overloaded for strings, since strings are often required to be compared by value rather than by reference. In the case of the == operator, string pointers are compared first, and if they are equal, the method returns true. Otherwise, the equality of the operands is null (if at least one of them is null, false is returned). Then the string lengths are compared. And then there is a character-by-word comparison of strings (that is, a comparison by value). This is done using pointers in unmanaged code (obviously for performance reasons), and also unwinding cycles is used (apparently from the same considerations, but these are details that are of little interest in this case). If details are interesting, you can look here.