C#Intermedio13 oct 2025

El Doble Rasero del Operador `==` en C#

snippet.c#
using System;

public class Money
{
    public decimal Amount { get; }
    public string Currency { get; }

    public Money(decimal amount, string currency)
    {
        Amount = amount;
        Currency = currency;
    }

    public static bool operator ==(Money? m1, Money? m2)
    {
        if (ReferenceEquals(m1, m2))
            return true;
        if (ReferenceEquals(m1, null) || ReferenceEquals(m2, null))
            return false;
        return m1.Amount == m2.Amount && m1.Currency == m2.Currency;
    }

    public static bool operator !=(Money? m1, Money? m2)
    {
        return !(m1 == m2);
    }

    public override bool Equals(object? obj)
    {
        if (obj is not Money other) return false;
        return Amount == other.Amount && Currency == other.Currency;
    }

    public override int GetHashCode()
    {
        return HashCode.Combine(Amount, Currency);
    }
}

public class Program
{
    public static void Main()
    {
        Money cash1 = new Money(100.00m, "USD");
        Money cash2 = new Money(100.00m, "USD");

        Console.WriteLine($"cash1 == cash2: {cash1 == cash2}");
        Console.WriteLine($"((object)cash1) == ((object)cash2): {((object)cash1) == ((object)cash2)}");
    }
}

¿Qué crees que imprime?

Salida Esperada

cash1 == cash2: True
((object)cash1) == ((object)cash2): True

⚠️ Salida Real

cash1 == cash2: True
((object)cash1) == ((object)cash2): False

¿Por qué pasa esto?

¡Agárrate fuerte, porque hoy el operador `==` en C# nos jugará una mala pasada! 🎭 Hemos definido una clase `Money` con su propio `operator ==` para comparar valores (cantidad y divisa), ¡no referencias! - Cuando comparamos `cash1 == cash2`, C# es **inteligente**. Ve que ambos son `Money`, encuentra nuestro `operator ==` sobrecargado y dice: "¡Ah, quieren igualdad por valor!", resultando en **true** como esperamos. ✅ - Pero aquí viene el giro: al castearlos a `((object)cash1) == ((object)cash2)`, C# se pone un poco miope. 👓 El compilador ve dos `object` y dice: "Hmm, `object` no tiene un `operator ==` sobrecargado que yo conozca, así que usaré la **igualdad por referencia** por defecto". 🤯 ¡Y boom! Como `cash1` y `cash2` son instancias diferentes en memoria, el resultado es **false**. 💥 Es como si `Money` tuviera una identidad secreta: es un superhéroe de la igualdad por valor, pero cuando se pone el traje de `object`, vuelve a ser un ciudadano común que solo sabe comparar referencias. ¡Cuidado con los disfraces! 🦸‍♂️

Conceptos relacionados

operator-overloadingtype-castingreference-equality