0

I noticed that I get an unexpected result when I execute this:

object v1 = "Hallo";
object v2 = "Hallo";

char[] v3 = { 'H', 'a', 'l', 'l', 'o' };
object v4 = new string(v3);

bool resultOfTwoObjectsThatAreActuallyStrings = v1 == v2;
bool anotherResultOfTwoObjectsThatAreAlsoStrings = v1 == v4;

Console.WriteLine("First result: " + resultOfTwoObjectsThatAreActuallyStrings);
Console.WriteLine("Second result: " + anotherResultOfTwoObjectsThatAreAlsoStrings);

I would expect that I am doing exactly the same thing for both variables, but I get one time false and one time true.

Can anyone explain this to me?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
David Mason
  • 915
  • 1
  • 9
  • 27
  • 1
    Does [this](https://stackoverflow.com/questions/814878/c-sharp-difference-between-and-equals) answer your question? You are not calling the `==` operator that takes 2 strings, which compares the characters. – Sweeper Oct 10 '21 at 09:31
  • Does this answer your question? [C# difference between == and Equals()](https://stackoverflow.com/questions/814878/c-sharp-difference-between-and-equals) – Ermiya Eskandary Oct 10 '21 at 09:33
  • 3
    The missing piece I think is string interning: https://learn.microsoft.com/en-us/dotnet/api/system.string.intern?view=net-5.0#remarks. `v1` and `v2` actually refer to the same object, because those string literals are interned as described in the above link. But the way you built `v4` string prevents that, so it refers to another object (even though that another object contains the same string). – Evk Oct 10 '21 at 09:40

1 Answers1

1

C# operators aren't virtual.

When the compile-time type of the two variables is object, the operator object == object is used, which does a reference comparison. When the compile-time of the two variables is string, the operator string == string is used, which does a value comparison.

Why is v1 == v2 true? Because compile-time constants are automatically interned - v1 and v2 both point to the same memory, and as such, the reference comparison returns true.

Why is v1 == v4 false? Because you have two different objects with the same value, and the reference comparison returns false.

For bonus points, if you do object v4 = new string(v3).Intern();, you should get v1 == v4 as true. But the correct approach is to use the string == string operator (or string.Equals and friends) when you want value comparison.

Do not rely on two strings with the same value to always have the same reference, nor all strings having a different reference. If you always do a value comparison, two equal references will still give you a quick "yep, they're the same"; if you have the two as object variables, you will always get reference comparison.

Luaan
  • 62,244
  • 7
  • 97
  • 116