5

I am confusing about using == in (c#) when I use literal string like here:

object a="hello";
object b="hello";

the comparison a==b will be true.

but when I use object like here:

object c=new StringBuilder("hello").ToString();
object d=new StringBuilder("hello").ToString();

the comparison a==b will be false.

even though a,b,c,d all of type System.Object in compile time and == operator compare values depends on their values in compile time.

I use extension method to get type of varabiles during compile time:

public static class MiscExtensions
{
    public static Type GetCompileTimeType<T>(this T dummy)
    { return typeof(T); }
}
Matthias Seifert
  • 2,033
  • 3
  • 29
  • 41
mark
  • 73
  • 4
  • 3
    Interned string object compared with `==` as reference equality will return false (see https://stackoverflow.com/questions/1766492/overloading-operator-versus-equals). – Tetsuya Yamamoto Aug 29 '17 at 09:27
  • I think you are more confused about different types in C#. `Object`, `string` and `StringBuilder` are not the same, that's why they have different names. ;) – waka Aug 29 '17 at 09:29
  • similar questions here : https://stackoverflow.com/questions/27710665/comparing-values-using-operator – Ankit Aug 29 '17 at 09:37
  • 1
    Why are you using `GetCompileTimeType` for exactly? I don't see how it's relevant to your question – Rob Aug 29 '17 at 10:49
  • Since == operator determined based on the compile-time I was confused because this method determine that all variables are object type at compile-time. after answers I have recognized that no matter if they are all objects, but what is important here if these objects (a&b) or (c&d) point to same memory allocation or not. – mark Aug 29 '17 at 11:33
  • This is the same reason you can't compare strings using `==` in Java: They are different objects. (So you shoud use the `equals` method). – online Thomas Sep 04 '17 at 10:15

6 Answers6

17
object a="hello";
object b="hello";

Here the compiler creates a single string instance for the literal "hello". So a and b point to the same instance.

In your second snippet c and d point to different string instances.

The important point however is that a == b and c == d don't call the == operator of the string class, but of object. So a simple reference comparison is executed, not a string comparison.

René Vogt
  • 43,056
  • 14
  • 77
  • 99
  • @mark have a look to the official documentation. They say that equality is done by reference instead for string. René Vogt is correct with this answer – OrcusZ Aug 29 '17 at 09:30
7

Note here that you are comparing objectand not string !

This would have given true :

string c = new StringBuilder("hello").ToString();
string d = new StringBuilder("hello").ToString();

c == d; // true

or this :

var c = new StringBuilder("hello").ToString();
var d = new StringBuilder("hello").ToString();

c == d; // true

(because in this case, var will implicitly type the variables as the result of the expression, StringBuilder.ToString(), which is string), see here for more information


Don't mix object comparison and string comparison.

On your basic case, comparison led to true because it was actually the same object !

On the second case, you have two "new" statements, hence two different string builder, which generates two new string objects. Not the same constant string object.

The comparison used is determined by the type of your variables.

Pac0
  • 21,465
  • 8
  • 65
  • 74
  • 1
    Adding to this answer, here's a link that [explains the var-keyword in more detail](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/var) – waka Aug 29 '17 at 09:35
  • yes, I will add a word on this in my answer, thank you – Pac0 Aug 29 '17 at 09:39
2

For reference types other than string, == returns true if its two operands refer to the same object.

In first example:

object a="hello";
object b="hello";

a and b point to the same object, so they are equal, but in second:

object c=new StringBuilder("hello").ToString();
object d=new StringBuilder("hello").ToString();

you create two different instances of StringBuilder: c and d, so they point to different objects and are NOT equal (false)

More details you can find on Microsoft Docs.

Markiian Benovskyi
  • 2,137
  • 22
  • 29
2

From the msdn page:

For predefined value types, the equality operator (==) returns true if the values of its operands are equal, false otherwise. For reference types other than string, == returns true if its two operands refer to the same object. For the string type, == compares the values of the strings.

So both comparisons should not be equal, since you are specifically casting to an object instead of a string.

However the c# compiler is optimized and recognizes that you are using two identical string literals, thus the compiler merges the two strings into one object, hence the object comparison is true. but the compiler cannot merge the StringBuilder instances since you are constructing new objects using the new keyword.

Peter
  • 1,361
  • 15
  • 19
1

When you use the constant string "hello" the compiler will generate an interned version of this string and use this value for both a and b.

When you use a StringBuilder and ToString two separate instances of a string containing "hello" will be compared.

If you want to check for string equality, you should use the Equals() method

Sylence
  • 2,975
  • 2
  • 24
  • 31
1
object a="hello";
object b="hello";

Here both a and b are pointing to same object. To be specific they are pointing to same memory. Whereas in second example

object c=new StringBuilder("hello").ToString();
object d=new StringBuilder("hello").ToString();

Here you are creating a new instance, to be specific the memory location varies for both c and d. so that is the reason a==b and c!=d.

Ajithesh Gupta
  • 87
  • 2
  • 13