如何在不破坏现有对象的情况下,仅检查两个对象的属性是否相等.等于()

本文关键字:对象 两个 等于 是否 属性 检查 情况下 | 更新日期: 2023-09-27 17:59:31

基本上,GethashCode是不同的,即使它们包含相同的属性值。。。那么,为什么默认返回diff散列码呢?

public class User
{
    public Int32 Id { get; set; }
    public String Username { get; set; }
}
User a = new User();
a.Id = 1;
a.Username = "Hello";
User b = new User();
b.Id = 1;
b.Username = "Hello";
Console.WriteLine("Hash A: {0} | Hash B: {1}", a.GetHashCode(), b.GetHashCode());
//Hash A: 37121646 | Hash B: 45592480 <-- these values change each time I rerun the app?

有没有一种更合适的方法来制作它,这样我就不会破坏Object。Equals适用于我的对象,但仍然可以根据参数值进行自己的Equals检查?

我之所以这么问,是因为我有一个服务:SynchronizeUsers(),它下载一组用户。与其清除我的用户缓存,我宁愿只更新需要更新的用户,删除synch所说的用户,然后添加新的用户。但是,我不能只做Object。对这些对象执行Equals()。

如何在不破坏现有对象的情况下,仅检查两个对象的属性是否相等.等于()

回答为时已晚,但可能会有人来这里,我需要知道我的想法是对是错。如果严格考虑值,那么为什么不将对象设置为JSON并比较JSON字符串呢?类似:

if (JsonConvert.SerializeObject(obj1) == JsonConvert.SerializeObject(obj2)) continue;

您是否尝试过实现自己的IEqualityComparer?您可以将此传递给。Equals()重载来定义您自己的自定义相等逻辑,如中

用户A=用户B,即使它们是不同的实例,如果属性x、y、z相同。

请参阅:MSDN

编辑:我应该写过,你可以实例化EqualityComparer,并将两个实例传递给它的Equals()方法,然后得到一个bool。基本控制台应用程序。。。将显示真、假、假。事物是琐碎的,具有显示的两个属性。

var comparer = new ThingEqualityComparer();
Console.WriteLine(comparer.Equals(new Thing() { Id = 1, Name = "1" }, new Thing() { Id = 1, Name = "1" }));
Console.WriteLine(comparer.Equals(new Thing() { Id = 1, Name = "1" }, new Thing() { Id = 2, Name = "2" }));
Console.WriteLine(comparer.Equals(new Thing() { Id = 1, Name = "1" }, null));

class ThingEqualityComparer : IEqualityComparer<Thing>
{
    public bool Equals(Thing x, Thing y)
    {
        if (x == null || y == null)
            return false;
        return (x.Id == y.Id && x.Name == y.Name);
    }
    public int GetHashCode(Thing obj)
    {
        return obj.GetHashCode();
    }
}

如果你安装了ReSharper(值得!),那么你所要做的就是:

Alt+Insert

将光标放在类中。偏类有利于隐藏样板。

它将自动为每个属性实现相等性检查。

(选择所有属性w/Ctrl+A,然后您可以检查所有w/Space!)

当超过GetEquals()时,建议超过GetHashCode()。

http://msdn.microsoft.com/en-us/library/ms173147%28v=vs.80%29.aspx

例如

public override int GetHashCode()
{
    return this.Username.GetHashCode() * this.Id;
}

这里有一个解决方案,它不需要类中的任何自定义逻辑,并使用泛型来确保两个参数(obj1和obj2)在编译时是相同的类型:

  public static class ObjectComparerUtility
  {
    public static bool ObjectsAreEqual<T>(T obj1, T obj2)
    {
      var obj1Serialized = JsonConvert.SerializeObject(obj1);
      var obj2Serialized = JsonConvert.SerializeObject(obj2);
      return obj1Serialized == obj2Serialized;
    }
  }

用法:

  var c1 = new ConcreteType { Foo = "test1" };
  var c2 = new ConcreteType { Foo = "test1" };
  var areEqual = ObjectComparerUtility.ObjectsAreEqual(c1, c2);
  Assert.IsTrue(areEqual);

为什么不编写自己的Equality方法?即

User a = new User();
a.Id = 1;
a.Username = "Hello";
User b = new User();
b.Id = 1;
b.Username = "Hello";
a.IsEqualTo(b);

其中IsEqualTo在用户类中定义为:

Public bool IsEqualTo(user compareTo)
{
  return (UserName == compareTo.UserName && Id == compareTo.Id);
}

如果您只想对事物进行散列,请使用扩展方法来生成散列。

public static int GenerateHash(this User myUser){
    return myUser.UserName.GetHashCode() ^ ... other properties....
}

然后在你的代码中你可以做:

Console.WriteLine("Hash A: {0} | Hash B: {1}", a.GenerateHash(), b.GenerateHash());

这将使一切完好无损,不应破坏其他任何东西。如果你正在寻找一种比较对象的方法,你可以使用一种扩展方法:

public static int AreEqual(this User myUser, User someOther){
    return myUser.UserName == someOther.UserName && ...  other properties.
}

用法如下:

if(a.AreEqual(b)){
    // these are equal have fun.
}

提供的代码定义了一个具有FirstName和LastName属性的Person类。该类重写Equals和GetHashCode方法,这两个方法分别用于比较对象和为对象生成哈希代码。

Equals方法通过检查两个Person对象是否属于同一类型并且具有相同的FirstName和LastName值来比较它们。如果不满足这些条件中的任何一个,该方法将返回false。否则,返回true。

GetHashCode方法通过使用哈希代码计算算法组合Person对象的FirstName和LastName属性的哈希代码,为Person对象生成哈希代码。这对于在基于哈希的集合(如字典或哈希集)中使用Person对象是必要的。

Equals和GetHashCode的这种实现通常是正确的,并遵循重写这些方法的准则。它确保两个Person对象在具有相同的FirstName和LastName值的情况下被视为相等。此外,哈希代码计算基于相同的属性,为基于哈希的集合提供了一致的行为。

public class Person
{
       public string FirstName { get; set; }
       public string LastName { get; set; }
   
       public override bool Equals(object obj)
       {
           if (obj == null || GetType() != obj.GetType())
           {
               return false;
           }
   
           Person otherPerson = (Person)obj;
   
           return FirstName == otherPerson.FirstName && LastName == otherPerson.LastName;
       }
   
       public override int GetHashCode()
       {
           int hashCode = 17;
           hashCode = hashCode * 23 + FirstName.GetHashCode();
           hashCode = hashCode * 23 + LastName.GetHashCode();
           return hashCode;
       }
}

添加一个方法:

public class User
{
    public int UserID { get; set; }
    public bool IsUser(object obj) 
    {
        return (obj is User && ((User)obj).UserID == this.UserID);
    }
}
字符串数组是比较的排除列表。它使用反射,但性能非常好。请查看apache commons lang 3库
CompareToBuilder.reflectionCompare(arg0, arg1, new String[]{"UID", "uidcount"})