我应该重载==运营商吗?

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

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

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

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

如果没有, 那么正确的方法是重载==运算符以明确检查所有字段的等价性吗?

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

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

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

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方法。

编辑:

我在比较中编写了以下快速示例以使用reflection。 这将是更加全面的,如果人们想要我,我可能会尝试在其上做博客:

 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; } } 

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

如果要检查两个不同对象的内容是否相等,那么您必须自己编写代码,以这种或那种方式自己完成。 有可能用reflection做( MbUnit测试框架在这些方面做了一些事情),但是性能损失很大,很有可能它不会完全达到预期的效果,你应该实现==Equals和手动GetHashCode

除了==运算符之外,正确的方法是重载Tweet类的equals方法,如此处所述。

那会检查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; } } 

您可以使用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; } }