【问题标题】:compare objects for equality - if the values of the properties are the same比较对象是否相等 - 如果属性的值相同
【发布时间】:2022-01-04 08:33:44
【问题描述】:

我不经常使用。所以这就是我问这个问题的原因。

但显然在 C# 中不可能只与对象进行简单的比较。所以我当然先用谷歌搜索,但我只找到了非常多余的解决方案。而且我知道您可以通过 javascript 序列化对象,然后返回字符串,然后相互比较属性。

因为我只想比较两个简单的对象——如果属性的值相同的话。所以我有这个:

public class Person
{

    public string FirstName { get; set; }
    public string LastName { get; set; }   


    public Person()
    {
    }

    public bool IsEqualTo(Person compareTo)
    {
        return (FirstName == compareTo.FirstName && LastName == compareTo.LastName);
    }

 public static bool AreEqual<AnyType>(AnyType mass1, AnyType mass2) where AnyType : IComparable<AnyType>
        {
            return mass1.CompareTo(mass2) == 0;
        }


    public Person(string lastName, string firstName)
    {
        this.FirstName = firstName;
        this.LastName = lastName;
    }  
}

但是我不能像这样使用 AreEqual 方法:

var person = new Person("Niels","Engelen");
var person99 = new Person("Niels", "Engelen")

 var equals = Person.AreEqual(person,  person99);

所以:

 var equals = person.CompareTo(person99);

这当然行不通。

那么只有这样有效吗?

 public bool IsEqualTo(Person compareTo)
    {
        return (FirstName == compareTo.FirstName && LastName == compareTo.LastName);
    }

比输出:

   var equals = person.IsEqualTo(person99);

会是真的。

但是你必须比较每个属性。

那么就没有比较对象的短方法吗?

谢谢。

很奇怪,在像 C# 这样庞大的语言中,您没有可以比较对象是否相等的方法。

我又搜索了一些,发现你是用记录做的:

var record1 = new Person.Hello("Niels", "Engelen");
var record2 = new Person.Hello("Niels", "Engelen");

var equalRecords = record1 == record2;
Console.WriteLine("Records " +  equalRecords);

即使在 Javascript 中,您也可以轻松比较复杂的对象。

【问题讨论】:

  • 您可以在较新的 C# 版本中使用 record 类型而不是 class,这将为您自动生成相等检查方法和运算符。除此之外,不,没有内置的自动魔法方法。

标签: c# icomparable


【解决方案1】:

您可以使用反射循环遍历类的所有属性并进行比较:

public bool IsEqualTo(Person other)
    {
        foreach(var prop in typeof(Person).GetProperties())
        {
            var value1 = prop.GetValue(this);
            var value2 = prop.GetValue(other);
            if(!value1.Equals(value2))
            {
                return false;
            }
        }
        return true;
    }

如果您添加或删除任何属性,则无需修改您的 IsEqualTo 方法。这种方法的缺点是反射通常性能较低。如果您进行大量比较,这可能不是一个好的解决方案。

【讨论】:

  • 啊,谢谢。看起来更好
  • 但是现在有一个方法可以做比较对象吗?即使使用 javascript,您也可以轻松退出。
【解决方案2】:

假设您使用的是 c#9 或更高版本,您可以简单地使用将您的类型声明为记录,并从开箱即用的编译器中获取基于值的比较:

public record Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

注意:无论您是否切换到记录,您都应该考虑尽可能使您的类型不可变 - 因此将 {get;set;} 更改为 {get;init}{get;} 仅属性。

如果您使用的是旧版本的 c#,则应考虑实现 IEquatable&lt;T&gt; 接口。
重要提示:

如果您实现 IEquatable,您还应该重写 Equals(Object) 和 GetHashCode() 的基类实现,以便它们的行为与 Equals(T) 方法的行为一致。如果您确实覆盖了 Equals(Object),那么在调用类上的静态 Equals(System.Object, System.Object) 方法时也会调用被覆盖的实现。此外,您应该重载 op_Equality 和 op_Inequality 运算符。这可确保所有相等性测试返回一致的结果。

【讨论】:

    【解决方案3】:

    实现接口IEquatable&lt;T&gt;,然后你可以使用方法Equals for Person。

     public class Person : IEquatable<Person>
       {
    
        public string FirstName { get; set; }
        public string LastName { get; set; }
    
    
        public Person()
        {
        }
    
        public bool Equals(Person compareTo)
        {
            return (FirstName == compareTo.FirstName && LastName == compareTo.LastName);
        }
    
        public override int GetHashCode()
        {
            return HashCode.Combine(FirstName, LastName);
        }
    
        public Person(string lastName, string firstName)
        {
            this.FirstName = firstName;
            this.LastName = lastName;
        }
      }
    
      var person1 = new Person("test", "test");
      var person2 = new Person("test", "test");
      Assert.AreEqual(person1, person2);
      //true
    

    您还必须重写方法GetHashCode

    【讨论】:

    • 我说的。现在它取决于属性。但是就没有一个独立于属性的简单方法可以使用吗?
    • 顺便说一句,这一切都准备好了: public bool IsEqualTo(Person compareTo) { return (FirstName == compareTo.FirstName && LastName == compareTo.LastName); } 你不必再使用 IEquatable
    猜你喜欢
    • 1970-01-01
    • 2010-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多