2013-12-20 67 views
5

如果我有像一个对象:如何检查对象是否等于同一个类的新对象?

public class Person 
{ 
    public int id {get;set;} 
    public string name {get;set;} 
} 

而且我想要的行为:

Person a = new Person(); 
Person b = new Person(); 

a == b; 

和一个== b返回true,我必须重写的Object.Equals()方法?或者有没有其他的方式来做到这一点,而不是重写Equals方法?

编辑

我想比较的数据,因为我想知道,如果我调用返回一个新的对象或大于新对象用不同的数据对象

回答

8

有几种方法可以做到这一点。默认情况下,Equals()==检查参考平等,意思是:

Person a = new Person(); 
Person b = a: 

a.Equals(b); //true 
a == b; //true 

因此,对象不是比较的值相等,这意味着:

Person a = new Person { id = 1, name = "person1" }; 
Person b = new Person { id = 1, name = "person1" }; 

a.Equals(b); //false 
a == b; //false 

要为它们的值可以覆盖比较对象Equals()GetHashcode()方法,像这样:

public override bool Equals(System.Object obj) 
{ 
    if (obj == null) 
     return false; 

    Person p = obj as Person; 
    if ((System.Object)p == null) 
     return false; 

    return (id == p.id) && (name == p.name); 
} 

public bool Equals(Person p) 
{ 
    if ((object)p == null) 
     return false; 

    return (id == p.id) && (name == p.name); 
} 

public override int GetHashCode() 
{ 
    return id.GetHashCode()^name.GetHashCode(); 
} 

现在你会看到其他结果比较时:

Person a = new Person { id = 1, name = "person1" }; 
Person b = new Person { id = 1, name = "person1" }; 
Person c = a; 

a == b; //false 
a == c; //true 
a.Equals(b); //true 
a.Equals(c); //true 

==运算符未被覆盖,因此仍然进行参考比较。

public static bool operator ==(Person a, Person b) 
{ 
    if (System.Object.ReferenceEquals(a, b)) 
     return true; 

    if ((object)a == null || (object)b == null) 
     return false; 

    return a.id == b.id && a.name == b.name; 
} 

public static bool operator !=(Person a, Person b) 
{ 
    return !(a == b); 
} 

现在运行检查结果如下:

Person a = new Person { id = 1, name = "person1" }; 
Person b = new Person { id = 1, name = "person1" }; 
Person c = a; 

a == b; //true 
a == c; //true 
a.Equals(b); //true 
a.Equals(c); //true 

更多阅读:

这可以通过重载它还有 !=操作来解决
+1

有关实现自定义GetHashCode实现的更好方法,请参阅http://stackoverflow.com/questions/263400/what-is-the-best-algorithm-for-an-overridden-system-object-gethashcode。另外,为什么不在比较null时使用ReferenceEquals并避免投射?名称比较是否区分大小写?我猜并不是因为在名称方面,案件通常不重要。 – tvanfosson

0
object.Equals(object2); 

一个外部方法你案例:

a.Equals(b); 
+1

这只是比较引用,而不是数据(可能是什么OP希望,但是,他们没有指定)。 – James

2

这一切都取决于你想比较一下,在默认情况下Equals将参照因此比较

a == b 

在你的例子中将永远是false。不过,如果你不喜欢的东西

Person a = new Person(); 
Person b = a; 

然后a == b会因为无论ab使用相同参考true

我是否必须重写Object.Equals()方法?

覆盖EqualsGetHashCode是推荐的方法,但是(出于参数的缘故),这不是唯一的方法。例如,您可以覆盖==运算符,并在那里进行比较。但是,单独沿着这条路线有限制。

大多数比较检查,如果不是全部,将在内部使用Equals,这就是为什么它是首选方法。见Guidelines for Overloading Equals() and Operator ==

+0

我试图避免覆盖路线,但最终似乎是解决我的问题,谢谢。 –

0

假设测试是

Test a = new Test() { Num = 1, Str = "Hi" }; 
Test b = new Test() { Num = 1, Str = "Hi" }; 
bool areEqual = System.Object.ReferenceEquals(a, b); 
2

你想重载==操作。因此,您应该首先覆盖Equals。如果您覆盖Equals,则应始终覆盖GetHashCode。如果你重载==运营商还必须重载!=操作:

public class Person 
{ 
    public int id {get;set;} 
    public string name {get;set;} 

    public override bool Equals(object obj) 
    { 
     Person p2 = obj as Person; 
     if (object.ReferenceEquals(null, p2)) return false; 
     return id == p2.id; 
    } 

    public static bool operator ==(Person p1, Person p2) 
    { 
     if (object.ReferenceEquals(null, p1)) 
      return object.ReferenceEquals(null, p2); 
     else if (object.ReferenceEquals(null, p2)) 
      return false; 
     return p1.Equals(p2); 
    } 

    public static bool operator !=(Person p1, Person p2) 
    { 
     if (object.ReferenceEquals(null, p1)) 
      return !object.ReferenceEquals(null, p2); 
     else if (object.ReferenceEquals(null, p2)) 
      return true; 
     return !p1.Equals(p2); 
    } 

    public override int GetHashCode() 
    { 
     return id ; 
    } 
} 

现在这种比较,而不是唯一的参考值(id):

Person p1 = new Person { id = 1, name = "Jeff" }; 
Person p2 = new Person { id = 2, name = "Tim" }; 
bool equalPersons = p1 == p2; // false 
Person p3 = new Person { id = 1, name = "Jeff 2.0" }; // same id -> equal 
equalPersons = p1 == p3; // true 

MSDN: Guidelines for Overloading Equals() and Operator ==

0

是。你想和Person的对象进行比较,你需要从Object类中覆盖equals和hashcode方法,默认情况下引用check(==)是通过equals方法完成的。

假设两个具有相同名称和id的人员只能被视为同等使用equals和hashcode方法中的这些属性。

使用Java IDE提供的方式生成equals和hashcode更容易。你可以尝试下面的代码。

public class Person { 

    private int id; 
    private String name; 

    // id getters and setters 

    // name getters and setters 

    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + id; 
     result = prime * result + ((name == null) ? 0 : name.hashCode()); 
     return result; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) 
      return true; 
     if (obj == null) 
      return false; 
     if (getClass() != obj.getClass()) 
      return false; 
     Person other = (Person) obj; 
     if (id != other.id) 
      return false; 
     if (name == null) { 
      if (other.name != null) 
       return false; 
     } else if (!name.equals(other.name)) 
      return false; 
     return true; 
    } 

} 
相关问题