简体   繁体   English

Object.Equals() 方法在看似相等的对象上返回 false

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

I'm writing a C# application where I populate a DataGridView with a list of objects of type Airport .我正在编写一个 C# 应用程序,在其中使用Airport类型的对象列表填充DataGridView 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> .仅供参考dgvF是一个DataGridView包含flights List<Flights> ,我也有一个dgvA我的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 .但是, if(delete.Equals(aO) || delete.Equals(aD))if (airports.Contains(delete))行永远不会返回 true,我在调试模式下运行应用程序,尽管在某一时刻delete{"TIJ- Tijuana"} {"TIJ - Tijuana"} {"TIJ- Tijuana"}aD{"TIJ - Tijuana"}布尔运算仍然返回false I don't really know why.我真的不知道为什么。 Is it because of my .toString() overrided method?是因为我的.toString()覆盖方法吗? Because I need it to display the full Airport name on my DataGridView of Flight methods.因为我需要它在 Flight 方法的DataGridView上显示完整的机场名称。

My Airport and Flight classes are defined as follows:我的AirportFlight类定义如下:

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.使用object.Equals匹配将通过引用完成。 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.您应该在您的类中覆盖和实现EqualsGetHashCode以影响比较。

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:正如帕特里克所说,您需要覆盖EqualsGetHashCode ,这就是我的做法:

Refer to https://msdn.microsoft.com/en-us/library/vstudio/336aedhh%28v=vs.100%29.aspx for more info.有关详细信息,请参阅https://msdn.microsoft.com/en-us/library/vstudio/336aedhh%28v=vs.100%29.aspx

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

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 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如果当前实例是引用类型,则 Equals(Object) 方法测试引用相等性,调用 Equals(Object) 方法等效于调用 ReferenceEquals 方法

  public override bool Equals(Object obj) {
  // Perform an equality check on two rectangles (Point object pairs). 
      if (obj == null || GetType() != obj.GetType()) 
         return false;
       Airport r = (Airport)obj;
      return fromCity.Equals(r.fromCity) && toCity .Equals(r.toCity );
  }

  public override int GetHashCode() {
     return Tuple.Create(fromCity, toCity ).GetHashCode();
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM