21

Please help understand this behavior. When I use this:

bool a1 = (object)("string" + 1) == ("string" + 1);

The result is false

But when I use this

bool a2 = (object)("string" + "1") == ("string" + "1"); 

The result is true

So, why a1 != a2?

6
  • I don't know exactly why, but I know you shouldn't be checking string quality using "==" anyways. object1.equals(object2) is the way to go with that, at least to my understanding. I didn't post this as an answer though because it probably doesn't answer your question. Commented Jun 27, 2013 at 19:47
  • Check this: stackoverflow.com/questions/3398604/… Commented Jun 27, 2013 at 19:49
  • 1
    @Ricky Mutschlechner: AFAIK the operator '==' == '.equals'. ;-) Commented Jun 27, 2013 at 19:52
  • 11
    @RickyMutschlechner In C#, == is fine for comparing strings, as long as they're both treated as strings - this is just a funky case when you're dealing with strings that are cast as objects. But "string" + 1 == "string1" still returns true. It's Java that you really need to use equals. The biggest reason I avoid Equals in .NET is that you have to check the first one for null every time, to avoid NullReferenceException, where using == works fine for comparing nulls. Commented Jun 27, 2013 at 19:52
  • @FabianBigler good to know! I'm definitely a Java user who has just recently started with C#, but this is definitely something I'll keep in mind. Thanks for sharing! Commented Jun 27, 2013 at 19:54

2 Answers 2

34

Casting to object forces a reference equality comparison.

In the first case two different string objects are generated at runtime. Since they are different instances the result is false.

In the second case the compiler notices that "string" + "1" is always going to be "string1" and interns the string and uses the same reference in both places. Since it is the same string reference, the result is true.

Sign up to request clarification or add additional context in comments.

3 Comments

@OP Just to add on, you should always compare strings with String.Equals
@Mataniko No, you should just make sure that your variables are of a compile time type string if you use operator ==. Use string.Equals only if one or more of the objects isn't statically typed to string (which should really be quite rare).
@Servy a more common use of string.equals is when you want to use different comparison systems. Ordinal and OrdinalIgnoreCase are things I tend to use a lot, especially because they're much faster than standard ==.
18

There are two important things going on here:

First, The expression "string" + 1 is evaluated at run-time while "string" + "1" is evaluated at compile-time.

Secondly, you're using reference comparison. The run-time generated strings actually reference different object while the compile-time generated strings reference the same object, so the first expression is false and the second expression is true.

If you're interested, the generated IL is:

// bool a1 = (object)("string" + 1) == ("string" + 1);
// bool a2 = (object)("string" + "1") == ("string" + "1");

IL_0000:  ldstr       "string"
IL_0005:  ldc.i4.1    
IL_0006:  box         System.Int32
IL_000B:  call        System.String.Concat
IL_0010:  ldstr       "string"
IL_0015:  ldc.i4.1    
IL_0016:  box         System.Int32
IL_001B:  call        System.String.Concat
IL_0020:  ceq         
IL_0022:  stloc.0     // a1
IL_0023:  ldstr       "string1"
IL_0028:  ldstr       "string1"
IL_002D:  ceq         
IL_002F:  stloc.1     // a2

1 Comment

Neat. Care to mention how one would view IL like this?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.