3

运算符在 C# 中如何==真正发挥作用?如果它用于比较A类的对象,它会尝试匹配A的所有属性,还是会寻找指向同一内存位置的指针(或者可能是其他东西)?

让我们创建一个假设的例子。我正在编写一个利用 Twitter API 的应用程序,它有一个Tweet类,它具有单个推文的所有属性:文本、发件人、日期和时间、来源等。如果我想比较Tweet类的对象是否等效,我可以使用:

Tweet a, b;
if (a == b)
{
//do something...
}

这会检查Tweet类在ab之间的所有属性的等价性吗?

如果不是,正确的方法是重载==运算符以显式检查所有字段的等价性吗?

更新:从前两个答案中,我是否正确地假设:

  • 如果没有为类重载==运算符或Equals方法,则使用对象==类的运算符。
  • 对象类的==运算符检查内存位置是否相等。
  • 我必须重载==运算符或Equals方法才能完成此任务。
  • 在重载中,我必须手动检查属性的等价性,所以没有办法半自动地进行,比如说,在循环中,对吧?

更新#2: Yuriy 发表评论说,可以==使用反射检查运算符中属性的等价性。如何才能做到这一点?你能给我一些示例代码吗?谢谢!

4

5 回答 5

4

==对于引用类型,运算符和方法的默认实现Equals()将简单地检查两个对象是否具有相同的引用,因此是相同的实例。

如果您想检查两个不同对象的内容是否相等,那么您必须自己编写代码以一种或另一种方式进行。可以使用反射(MbUnit测试框架在这些方面做一些事情),但会带来严重的性能损失,并且很有可能它不会完全按照您的预期进行,您应该手动实现==orEquals和 and GetHashCode

于 2009-10-29T00:52:53.993 回答
3

MSDN 有一个很好的例子来说明如何做到这一点:

   public override bool Equals(object o) 
   {
      try 
      {
         return (bool) (this == (DBBool) o);
      }
      catch 
      {
         return false;
      }
   }

然后你重载 == 和 !=:

// Equality operator. Returns dbNull if either operand is dbNull, 
   // otherwise returns dbTrue or dbFalse:
   public static DBBool operator ==(DBBool x, DBBool y) 
   {
      if (x.value == 0 || y.value == 0) return dbNull;
      return x.value == y.value? dbTrue: dbFalse;
   }

   // Inequality operator. Returns dbNull if either operand is
   // dbNull, otherwise returns dbTrue or dbFalse:
   public static DBBool operator !=(DBBool x, DBBool y) 
   {
      if (x.value == 0 || y.value == 0) return dbNull;
      return x.value != y.value? dbTrue: dbFalse;
   }

并且不要忘记重载 GetHash 方法。

编辑:

我编写了以下快速示例,用于在比较中使用反射。这必须更全面,如果人们希望我这样做,我可能会尝试在上面写一个博客:

public class TestEquals
{
    private int _x;
    public TestEquals(int x)
    {
        this._x = x;
    }

    public override bool Equals(object obj)
    {
        TestEquals te = (TestEquals)obj;
        if (te == null) return false;

        foreach (var field in typeof(TestEquals)
            .GetFields(BindingFlags.NonPublic | BindingFlags.Instance))
        {
            if (!field.GetValue(this).Equals(field.GetValue(te)))
                return false;
        }
        return true;
    }
}
于 2009-10-29T00:40:10.500 回答
2

正确的方法是重载 Tweet 类的 equals 方法以及 == 运算符,如此所述。

于 2009-10-29T00:33:24.023 回答
1

You can compare the properties using reflection:

var a = new Entity() { Name = "test", ID = "1" };
var b = new Entity() { Name = "test", ID = "1" };
var c = new Entity() { Name = "test", ID = "2" };
System.Diagnostics.Debug.WriteLine(a.Equals(b));//Returns true
System.Diagnostics.Debug.WriteLine(a.Equals(c));//Returns false


public class Entity
{
    public string Name { get; set; }
    public string ID { get; set; }
    public override bool Equals(object obj)
    {
        var t = obj.GetType();
        foreach (var p in t.GetProperties())
        {
            if (t.GetProperty(p.Name).GetValue(obj, null) != t.GetProperty(p.Name).GetValue(this, null))
                return false;
        }
        return true;
    }
}
于 2009-10-29T01:00:50.030 回答
1

这会检查 a 和 b 之间的 Tweet 类的所有属性的等价性吗?

如果不是,正确的方法是重载 == 运算符以显式检查所有字段的等价性吗?

您可以重载==运算符,或重载Equals函数。

编辑

@Yuriy 给出了一个很好的例子来兼容所有非公共变量。因为我也写了一个例子,这里是(我比较属性)

class TwitterItem
{
    private string myValue = "default value";
    public string Value1
    {
        get { return myValue; }
        set { myValue = value; }
    }
    public string Value2
    {
        get { return myValue; }
        set { myValue = value; }
    }
    public string Value3
    {
        get { return myValue; }
        set { myValue = value; }
    }

    public override bool Equals(object obj)
    {
        if (base.Equals(obj)) return true;

        Type type = typeof(TwitterItem);
        PropertyInfo[] properties = type.GetProperties();

        foreach (PropertyInfo property in properties)
        {
            if (false == property.GetValue(this, null).Equals(property.GetValue(obj, null)))
                return false;
        }

        return true;
    }
}
于 2009-10-29T00:34:11.533 回答