9

please look at the below code:

using System;
class MyClass
{
    static void Main()
    {
        object o = ".NET Framework";
        object o1 = new string(".NET Framework".ToCharArray());
        Console.WriteLine(o == o1);
        Console.WriteLine(o.Equals(o1));
    }
}

and the result is:
False
True

and now consider this one:

using System;
class MyClass
{
    static void Main()
    {
        object o = ".NET Framework";
        object o1 = ".NET Framework";
        Console.WriteLine(o == o1);
        Console.WriteLine(o.Equals(o1));
    }
}

and the result is:
True
True

“==” compares if the object references are same while “.Equals()” compares if the contents are same. and i want to know what is different between these codes?!

object o1 = new string(".NET Framework".ToCharArray());

and

object o1 = ".NET Framework"; 

both of them turn out an object but why results are different?

Masoud Darvishian
  • 3,754
  • 4
  • 33
  • 41
  • 5
    I guess you would hear about string `interning` in the answers and also that strings are immutable. – V4Vendetta May 03 '13 at 09:45
  • Duplicate of [Are string.Equals() and == operator really same?](http://stackoverflow.com/questions/3678792/are-string-equals-and-operator-really-same). Please try to search first. – CodeCaster May 03 '13 at 10:17
  • 2
    @CodeCaster: Not the same... this is about strings in objects and then compare them. – Martin Mulder May 03 '13 at 10:52
  • @Martin it has to do with string interning, whether you box them as object or not. The answer is in the answers to the question I linked. – CodeCaster May 03 '13 at 10:58
  • To compare it with the other articel, this question title could have been: Are **object**.Equals() and == operator really same. – Martin Mulder May 03 '13 at 11:01
  • @Martin as I said, the boxing doesn't matter. It has to do with string interning, as explained in the question I linked and its answers. `object foo = "bar"` does not keep `"bar"` from being a string. The interning will cause the strings that are the same at compile-time to refer to the same string instance, so comparing their references will show they are equal. This happens whether you refer to them as string or as object (or any type in between, if there were any). – CodeCaster May 03 '13 at 11:17

3 Answers3

15

both of them turn out an object but why results are different?

In the second case, you're using the same string constant for both the o and o1 assignment. C# guarantees that any two equal string constant expressions within the same program will refer to the same string object. So the values of o and o1 are the same reference.

While I can't find the more general form (for constant string expressions), your case is actually covered by section 2.4.4 of the C# spec:

When two or more string literals that are equivalent according to the string equality operator appear in the same program, these string literals refere to the same string instance.

EDIT: A quick note on the behaviour of ==:

  • If both operands have a compile-time type of ==, the overload provided by string will be used, which performs a content comparison
  • Otherwise, the "default" implementation which just compares references for equality will be used, as you stated in your question.

In your case, the compile-time types of the operands are both object, so it is genuinely using reference equality.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Does this realy answer his questions, because his question not only about `Equals` vs `==` but also about `object` vs `string`. – Martin Mulder May 03 '13 at 10:41
  • 1
    @MartinMulder: I think so, because the OP is already aware that `“==” compares if the object references are same` (in his case). I'll make that clearer though. – Jon Skeet May 03 '13 at 11:15
3

Perhaps you are confused because use are using the types object instead of string.

If you compare two objects via the operator ==, only the references to those objects are compared. And since two constant strings inside the same assembly are merge as one, they have the same reference.

If you would compare two strings via the operation == than enother method is used. String has an operator override for ==. See: http://msdn.microsoft.com/en-us/library/system.string.op_equality(v=vs.110).aspx. This override does not compare the reference, it compares the value of both objects. In your example, the compiler cannot now both types are of type string because you are using objects. That is why the string operation == is not used to compare o and o1.

Back to the Equals function. Equals is a function which can be overridden by inheriting classes. In this case, the string class has overridden it and replace it with his own method of comparison. Where object.Equals compares only references, string.Equals compares values.

EDIT

So... this will produre your "strange" values:

    object o = ".NET Framework";
    object o1 = new string(".NET Framework".ToCharArray());
    Console.WriteLine(o == o1); // Will prodcuce: False.
    Console.WriteLine(o.Equals(o1)); // Will prodcuce: True.

And this will produce expected values:

    string o = ".NET Framework";
    string o1 = new string(".NET Framework".ToCharArray());
    Console.WriteLine(o == o1); // Will prodcuce: True.
    Console.WriteLine(o.Equals(o1)); // Will prodcuce: True.
Martin Mulder
  • 12,642
  • 3
  • 25
  • 54
  • When we're using string data type it always does content comparison. and we either use “.Equals()” or “==” it always do content comparison. – Masoud Darvishian May 03 '13 at 10:07
  • @Mesut, but you are not using the type `string` for `o` and `o1`. You are using types `object`. – Martin Mulder May 03 '13 at 10:09
  • Does that mean the `string` type does _not_ override the `Equals(object)` method? Wouldn't that make it dangerous for use in Dictionaries as keys? – Chris Sinclair May 03 '13 at 10:26
  • Well... `string` DOES override the `Equals(object)`. That is why you see the result of the value-comparison instead of the reference comparison. If `string` did not override the `Equals` method, only the references would have been compared, resulting in false. – Martin Mulder May 03 '13 at 10:28
  • 1
    @MartinMulder Oh man. Too early in the morning for me. _Completely flipped the results of the test_. Thought `==` was reporting true, and `Equals` reporting false and everyone had gone bonkers. _DISREGARD ME_ :) – Chris Sinclair May 03 '13 at 10:32
2

Your second sample uses string from intern pool, that is why their reference is equal as well, whereas in your first code example you have two different string objects. Consider the following example.

object o = ".NET Framework";
object o1 = ".NET Framework";
object o2 = new string(".NET Framework".ToCharArray());
Console.WriteLine(o == o1);
Console.WriteLine(o.Equals(o1));
Console.WriteLine(Object.ReferenceEquals(o,o1)); //True
Console.WriteLine(Object.ReferenceEquals(o, o2)); //False

EDIT:

From the comments on other posts, I guess I should mention that the current behaviour for == with respect to string is different with other reference types:

== Operator (C# Reference)- MSDN

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 the following would result in true:

string o = ".NET Framework";
string o2 = new string(".NET Framework".ToCharArray());
Console.WriteLine(o == o1); //True

Because now the type is string, not object

Habib
  • 219,104
  • 29
  • 407
  • 436