我应该重载 == 运算符吗?
-
08-07-2019 - |
题
如何 ==
运算符在 C# 中真的起作用吗?如果它用于比较类的对象 A, ,它会尝试匹配所有 A的属性,还是会寻找指向同一内存位置(或者可能是其他位置)的指针?
让我们创建一个假设的例子。我正在编写一个利用 Twitter API 的应用程序,它有一个 鸣叫 类,它具有单个推文的所有属性:文本、发件人、日期和时间、来源等。如果我想比较类的对象 鸣叫 为了等效,我可以使用:
Tweet a, b;
if (a == b)
{
//do something...
}
那会吗 检查所有属性的等价性 的 鸣叫 类之间 A 和 乙?
如果不, 正确的方法是超载 ==
操作员 显式检查所有字段的等效性?
更新: 从前两个答案来看,我的假设是否正确:
- 如果
==
运算符或 等于 方法没有被类重载,==
运算符为 目的 使用类。 - 这
==
运算符为 目的 类检查内存位置是否相等。 - 我必须超载
==
操作员或 等于 方法来完成这个任务。 - 在重载中,我必须手动检查属性的等效性,所以 没有办法半自动地完成它,比如循环, , 正确的?
更新#2: Yuriy 评论说可以检查属性中的等价性 ==
运算符与 反射. 。如何才能做到这一点?你能给我一些示例代码吗?谢谢!
解决方案
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;
}
}
其他提示
对于引用类型,两者的默认实现 ==
运营商和 Equals()
方法将简单地检查两个对象是否具有相同的引用,因此是相同的实例。
如果您想检查两个不同对象的内容是否相等,那么您必须以一种或另一种方式自己编写代码来执行此操作。可以通过反射来完成( 兆单位 测试框架做了一些类似的事情),但是性能会受到严重影响,并且很有可能它不会完全达到您的预期,因此您应该实现 ==
或者 Equals
和 GetHashCode
用手。
正确的方法是除了 == 运算符之外还重载 Tweet 类的 equals 方法,如上所述 这里.
是否会检查 a 和 b 之间 Tweet 类的所有属性是否相等?
不
如果不是,正确的方法是否是重载 == 运算符以显式检查所有字段的等效性?
您可以超载 == 运算符,或重载 等于 功能。
编辑
@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;
}
}
您可以使用反射来比较属性:
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;
}
}