static void Main(string[] args)
        {
            Guy joe1 = new Guy("Joe", 37, 100);

            // True
            Guy joe2 = joe1;

            Console.WriteLine(ReferenceEquals(joe1, joe2));
            Console.WriteLine(joe1.Equals(joe2));
            Console.WriteLine(ReferenceEquals(null, null));

            // False
            joe2 = new Guy("Joe", 37, 100);
            Console.WriteLine(ReferenceEquals(joe1, joe2));
            Console.WriteLine(joe1.Equals(joe2));

            // Now that Equals() and GetHashCode() are implemented in EquatableGuy, the following will work:
            List <Guy> guys = new List <Guy>()
            {
                new Guy("Bob", 42, 125),
                new EquatableGuy(joe1.Name, joe1.Age, joe1.Cash),
                new Guy("ed", 39, 95)
            };

            // True
            Console.WriteLine(guys.Contains(joe1));

            // False
            Console.WriteLine(joe1 == joe2);

            // Object comparison with overwritten equals operators
            joe1 = new EquatableGuyWithOverload(joe1.Name, joe1.Age, joe1.Cash);
            joe2 = new EquatableGuyWithOverload(joe1.Name, joe1.Age, joe1.Cash);

            // Below does not work as expected beause its calling Guy's == & != operators
            // False
            Console.WriteLine(joe1 == joe2);
            // True
            Console.WriteLine(joe1 != joe2);

            // Cast to EquatableGuyWithOverload to call the correct == & !=
            // True
            Console.WriteLine((EquatableGuyWithOverload)joe1 == (EquatableGuyWithOverload)joe2);
            // False
            Console.WriteLine((EquatableGuyWithOverload)joe1 != (EquatableGuyWithOverload)joe2);

            joe2.ReceiveCash(25);

            // False
            Console.WriteLine((EquatableGuyWithOverload)joe1 == (EquatableGuyWithOverload)joe2);
            // True
            Console.WriteLine((EquatableGuyWithOverload)joe1 != (EquatableGuyWithOverload)joe2);

            // Now to make it work without casting
            EquatableGuyWithOverload joe3 = new EquatableGuyWithOverload(joe1.Name, joe1.Age, joe1.Cash);
            EquatableGuyWithOverload joe4 = new EquatableGuyWithOverload(joe1.Name, joe1.Age, joe1.Cash);

            // True
            Console.WriteLine(joe3 == joe4);
            // False
            Console.WriteLine(joe3 != joe4);

            Console.ReadKey();
        }
        static void Main(string[] args)
        {
            Guy joe1 = new Guy("Joe", 37, 100);

            // True
            Guy joe2 = joe1;
            Console.WriteLine(ReferenceEquals(joe1, joe2));
            Console.WriteLine(joe1.Equals(joe2));
            Console.WriteLine(ReferenceEquals(null, null));

            // False
            joe2 = new Guy("Joe", 37, 100);
            Console.WriteLine(ReferenceEquals(joe1, joe2));
            Console.WriteLine(joe1.Equals(joe2));

            // Now that Equals() and GetHashCode() are implemented in EquatableGuy, the following will work:
            List<Guy> guys = new List<Guy>()
            {
                new Guy("Bob", 42, 125),
                new EquatableGuy(joe1.Name, joe1.Age, joe1.Cash),
                new Guy("ed", 39, 95)
            };

            // True
            Console.WriteLine(guys.Contains(joe1));

            // False
            Console.WriteLine(joe1 == joe2);

            // Object comparison with overwritten equals operators
            joe1 = new EquatableGuyWithOverload(joe1.Name, joe1.Age, joe1.Cash);
            joe2 = new EquatableGuyWithOverload(joe1.Name, joe1.Age, joe1.Cash);

            // Below does not work as expected beause its calling Guy's == & != operators
            // False
            Console.WriteLine(joe1 == joe2);
            // True
            Console.WriteLine(joe1 != joe2);

            // Cast to EquatableGuyWithOverload to call the correct == & !=
            // True
            Console.WriteLine((EquatableGuyWithOverload)joe1 == (EquatableGuyWithOverload)joe2);
            // False
            Console.WriteLine((EquatableGuyWithOverload)joe1 != (EquatableGuyWithOverload)joe2);

            joe2.ReceiveCash(25);

            // False
            Console.WriteLine((EquatableGuyWithOverload)joe1 == (EquatableGuyWithOverload)joe2);
            // True
            Console.WriteLine((EquatableGuyWithOverload)joe1 != (EquatableGuyWithOverload)joe2);

            // Now to make it work without casting
            EquatableGuyWithOverload joe3 = new EquatableGuyWithOverload(joe1.Name, joe1.Age, joe1.Cash);
            EquatableGuyWithOverload joe4 = new EquatableGuyWithOverload(joe1.Name, joe1.Age, joe1.Cash);

            // True
            Console.WriteLine(joe3 == joe4);
            // False
            Console.WriteLine(joe3 != joe4);

            Console.ReadKey();
        }