Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Object.Equals() method returns false on seemingly equal object

Tags:

c#

I'm writing a C# application where I populate a DataGridView with a list of objects of type Airport. I'm currently writing the method to delete one after pressing a button.

For reference dgvF is a DataGridView containing the flights List<Flights>, I also have a dgvA for my airports List<Airports>.

private void bajaAeropuerto_Click(object sender, EventArgs e)
{
    String c = city.Text;
    String id = idAirport.Text;

    Airport delete = new Airport(c, id);

    //Select all Flights which reference the "delete" airport
    foreach (DataGridViewRow row in listaVuelos.Rows)
    {
        Flight v = (Flight)row.DataBoundItem;
        Airport aO = v.fromCity;
        Airport aD = v.toCity;

        if(delete.Equals(aO) || delete.Equals(aD))
        {
            dgvF.MultiSelect = true;
            row.Selected = true;
        }
    }

    if (airports.Contains(delete))
    {
        airports.Remove(delete);
    }
    else
    {
        //show message airport doesn't exist
    }

    dgvAirports.Update();
    dgvAirports.Refresh();
}

However, the if(delete.Equals(aO) || delete.Equals(aD)) and if (airports.Contains(delete)) lines never return true, I run the Application on debug mode and although at one point delete is {"TIJ- Tijuana"} and aD is {"TIJ - Tijuana"} the boolean operation still returns false. I don't really know why. Is it because of my .toString() overrided method? Because I need it to display the full Airport name on my DataGridView of Flight methods.

My Airport and Flight classes are defined as follows:

class Airport
{
    public String city{ get; set; }
    public String id { get; set; }

    public Airport(String ciudad, String id)
    {
        this.city = city;
        this.id = id;
    }

    public override string ToString()
    {
        return id + "- " + city; //Ej. MX- Mexico City
    }
}

and

class Flight
{
    public String id { get; set; }
    public Airport fromCity{ get; set; }
    public Airport toCity { get; set; }
    public int price{ get; set; }

    public Flight(String id, Aeropuerto origen, Aeropuerto destino, int precio)
    {
        this.id = id;
        this.fromCity = origen;
        this.toCity = destino;
        this.price= precio;
    }
}
like image 214
Ces Avatar asked Oct 25 '25 04:10

Ces


2 Answers

You are creating a new instance before trying to delete it. Matching using object.Equals will be done by reference. That means that the 'address pointer in memory' is checked against the 'address pointer in memory' of the new one. That can never be true.

You should override and implement Equals and GetHashCode in your class in order to influence the comparison.

public override bool Equals(object o)
{
    return o is Airport && ((Airport)o).id == this.id;
}

public override int GetHashCode()
{
    return this.id.GetHashCode();
}
like image 184
Patrick Hofman Avatar answered Oct 27 '25 19:10

Patrick Hofman


You need to override Equals and GetHashCode as Patrick has said, this is how I would do it:

Refer to https://msdn.microsoft.com/en-us/library/vstudio/336aedhh%28v=vs.100%29.aspx for more info.

class Airport
{
    ...

    public override bool equals(Object obj)
    {
        //types must be the exactly the same for non-sealed classes
        if (obj == null || obj.GetType() != GetType()) 
          return false;
        return equals((AirPort)obj);
    }

    private bool equals(AirPort other)
    {
        if (other == null)
          return false;
        return other.id == id; //only id should be needed if unique
    }

    public override int GetHashCode()
    {
        return id.GetHashCode(); //again, only id needed
    }
}

Or if sealed:

sealed class Airport
{
    ...

    public override bool equals(Object obj)
    {
        return equals(obj as AirPort);
    }

    public bool equals(AirPort other)
    {
        if (other == null)
          return false;
        return other.id == id; //only id should be needed if unique
    }

    public override int GetHashCode()
    {
        return id.GetHashCode(); //again, only id needed
    }
}
like image 30
weston Avatar answered Oct 27 '25 19:10

weston



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!