0

Strange behavior when comparing two string properties with the usage of reflection.

var a = new A
{
    X = "aa",
    B = 1
};

var b = new A
{
    X = "aa",
    B = 2
};

Type type = typeof(A);

object aObjValue = type.GetProperty("X")?.GetValue(a);
object bObjValue = type.GetProperty("X")?.GetValue(b);

Console.WriteLine("aObjValue == bObjValue : " + (aObjValue == bObjValue));
Console.WriteLine("aObjValue.Equals(bObjValue) : " + aObjValue.Equals(bObjValue));

a.X = Console.ReadLine();

aObjValue = type.GetProperty("X")?.GetValue(a);

Console.WriteLine("aObjValue == bObjValue : " + (aObjValue == bObjValue));
Console.WriteLine("aObjValue.Equals(bObjValue) : " + aObjValue.Equals(bObjValue));

a.X = "aa";

aObjValue = type.GetProperty("X")?.GetValue(a);

Console.WriteLine("aObjValue == bObjValue : " + (aObjValue == bObjValue));
Console.WriteLine("aObjValue.Equals(bObjValue) : " + aObjValue.Equals(bObjValue));

Console.ReadKey();

//aObjValue == bObjValue : True
//aObjValue.Equals(bObjValue) : True
//aa
//aObjValue == bObjValue : False
//aObjValue.Equals(bObjValue) : True
//aObjValue == bObjValue : True
//aObjValue.Equals(bObjValue) : True

When using Console.ReadLine() and manually assigning a.X to "aa" I'm getting false but when assigning it in code again I get true. This is unexpected behavior for me. Can someone explain me what is going on here?

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
Pawel
  • 525
  • 3
  • 16
  • Possible duplicate of [C# difference between == and Equals()](https://stackoverflow.com/questions/814878/c-sharp-difference-between-and-equals) – Michael Jul 17 '19 at 15:05
  • This is different. We are comparing strings and in both cases but in one case - when using Console.Read() and assigning string manually - output is different – Pawel Jul 17 '19 at 15:11
  • I have just used different ways to do the same but get different outputs – Pawel Jul 17 '19 at 15:14
  • 1
    This is really about strings being interned in C#, `Console.ReadLine` isn't returning an interned string so it is a completely different object reference. Change it to `string.Intern(Console.ReadLine())` and it should work as you expect. Or even better, don't use `object` in the first place. – DavidG Jul 17 '19 at 15:15

1 Answers1

4

So you know that string overloads the equality operator == to use Equals. But since you store them in a Object variable they are using the version from Object which just compares references.

Again string is a special type, it uses something that is called string interning to improve performance. So if you use a string literal "aa" this will not allocate new memory if there was already a string literal "aa". This is the case here. That is why the first aObjValue == bObjValue returns true, both are the same reference.

In the second case you enter the string "aa" to the console. This will not use string interning(which is a compiler feature), so it is a brand new instance of String. That is why the second aObjValue == bObjValue returns false. If you would cast them to String you could use == and you would get the expected behavior(same as String.Equals).

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939