[英]Should I Overload == Operator?
==
运算符如何在C#中真正起作用? 如果它用于比较A类的对象,它会尝试匹配A的所有属性,还是会寻找指向同一内存位置(或者其他东西)的指针?
让我们创建一个假设的例子。 我正在编写一个利用Twitter API的应用程序,它有一个Tweet类,它具有单个推文的所有属性:文本,发送者,日期和时间,源等。如果我想比较类Tweet的对象是否等价,我可以使用:
Tweet a, b;
if (a == b)
{
//do something...
}
那会检查 a和b之间Tweet类的所有属性的等价性吗?
如果没有, 那么正确的方法是重载==
运算符以明确检查所有字段的等价性吗?
更新:从前两个答案,我是正确的假设:
==
运算符或Equals方法,则使用对象类的==
运算符。 ==
运算符检查内存位置是否相等。 ==
运算符或Equals方法来完成此任务。 更新#2: Yuriy发表评论说,可以使用反射检查==
运算符中属性的等价性。 如何才能做到这一点? 你能给我一些示例代码吗? 谢谢!
对于引用类型, ==
运算符和Equals()
方法的默认实现将只检查两个对象是否具有相同的引用,因此是相同的实例。
如果要检查两个不同对象的内容是否相等,那么您必须自己编写代码,以这种或那种方式自己完成。 可以使用反射( MbUnit测试框架在这些方面做了一些事情),但是性能损失很大,很有可能它不会完全达到预期的效果,你应该实现==
或Equals
和手动GetHashCode
。
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方法,如所描述这里 。
那会检查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;
}
}
您可以使用反射比较属性:
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;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.