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;
}
}
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();
}
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
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With