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; } } ```