Equality in Reference Types

c#

Solution

There are two effects at work here:

String interning means that actually even if you perform a reference equality check, you'll still see `True`. You can fix that like this:

object o1 = new StringBuilder("ABC").ToString();
object o2 = new StringBuilder("ABC").ToString();

`System.String` overrides the `Equals` method to compare the contents of the strings:

This method performs an ordinal (case-sensitive and culture-insensitive) comparison.

You can see the difference here:

object o1 = new StringBuilder("ABC").ToString();
object o2 = new StringBuilder("ABC").ToString();
Console.WriteLine(o1.Equals(o2)); // Prints True due to overriding
Console.WriteLine(ReferenceEquals(o1, o2)); // Prints False

Your class doesn't override `Equals`, so you're getting the default implementation in `Object`, which is to compare references:

If the current instance is a reference type, the Equals(Object) method tests for reference equality, and a call to the Equals(Object) method is equivalent to a call to the ReferenceEquals method.

You could fix that reasonably easily by overriding `Equals`:

// It's easier to implement equality correctly on sealed classes
public sealed class Person
{
    private readonly string personName;

    public Person(string name)
    {
        if (name == null)
        {
            throw new ArgumentNullException("name");
        }
        this.personName = name;
    }

    public override bool Equals(object other)
    {
        Person person = other as Person;
        return person != null && person.personName.Equals(personName);
    }

    // Must override GetHashCode at the same time...
    public override int GetHashCode()
    {
        // Just delegate to the name here - it's the only thing we're
        // using in the equality check
        return personName.GetHashCode();
    }
}

Note that in the `Equals` implementation we could have used:

return person != null && person.personName == personName;

... because `string` also overloads the `==` operator. But that's a different matter :)

Problem

I am a little confused on content equality in reference types specifically. I am not overriding Equality in either case - so why is the behavior different. See 2 simple code examples: Example 1: Returns True ``` class Program { static void Main(string[] args) { object o1 = "ABC"; object o2 = "ABC"; Console.WriteLine("object1 and object2: {0}", o1.Equals(o2)); } } ``` Example 2: Both statements return False ``` class Program { static void Main(string[] args) { Person person1 = new Person("John"); Person person2 = new Person("John"); Console.WriteLine("person1 and person2: {0}", person1.Equals(person2)); Console.WriteLine("person1 and person2: {0}", ((object)person1).Equals((object)person2)); Console.ReadLine(); } } public class Person { private string personName; public Person(string name) { this.personName = name; } } ```

Original source