C# 两个相等的.NET对象don';我不说是
我有以下代码:C# 两个相等的.NET对象don';我不说是,c#,equals,equality,C#,Equals,Equality,我有以下代码: object val1 = 1; object val2 = 1; bool result1 = (val1 == val2);//Equals false bool result2 = val1.Equals(val2); //Equals true 怎么回事?使用.Equals()方法是否是解决此问题的唯一方法?是=检查引用是否相等。在要比较内容的位置使用Equals 您可能想知道,为什么对象如此。将整型(值类型)设置为对象变量时,会发生称为装箱的操作。此操作将值类型包装
object val1 = 1;
object val2 = 1;
bool result1 = (val1 == val2);//Equals false
bool result2 = val1.Equals(val2); //Equals true
怎么回事?使用.Equals()方法是否是解决此问题的唯一方法?是<代码>=检查引用是否相等。在要比较内容的位置使用
Equals
您可能想知道,为什么对象如此。将整型(值类型)设置为对象变量时,会发生称为装箱的操作。此操作将值类型包装到对象中,并将其放入堆中并返回引用。这种情况会发生两次,引用会变得不同(尽管值相同)。这是因为当您将它们强制转换为对象时,它们会“转换”为对int值的引用。这两个参考值并不相等。
但是equals比较引用的值而不是引用。运算符
==
是静态的,而不是虚拟的,因此行为由静态类型而不是运行时类型决定。引用类型的对象上的==
的默认实现是比较引用(尽管类型可以实现不同的行为,例如string
)。您有两个不同的对象,它们没有相同的引用,因此=
返回false
正如你所指出的,解决办法是使用Equals。Equals是一种虚拟方法。由于value1
具有运行时类型Int32
,因此您最终会调用它。从.NET Reflector中,您可以看到此功能的实现如下所示:
public override bool Equals(object obj)
{
return ((obj is int) && (this == ((int) obj)));
}
换句话说,它检查参数的类型是否为int
,如果是,则将其强制转换并使用为int
定义的=
。这将比较整数的值
使用.Equals()方法是否是解决此问题的唯一方法
另一种方法是将对象强制转换为
int
,然后使用=
,就像Int32.Equals的实现一样 如果两个对象指向内存中的相同空间,则它们是相等的
val1 == val1; //Equals true
正如tc所指出的,您可以使操作员过载
public static bool operator ==(Object a, Object b)
这样,运算符==
的行为将是此方法定义的行为
您还应该重载运算符=代码>当您重载时,检查两个对象是否相同。事实并非如此。它们表示相同的数字,但存储在内存中的不同位置
val1 == val1; //Equals true
这就像比较两个苹果。两者都是苹果,外观相同,但它们是不同的对象。如果使用的不是对象,而是自定义类,则可以重写==和!=操作员,并且可能应该实现IEqualityComparer
接口
public static bool operator ==(MyType left, MyType right)
{
//code here, don't forget about NULLS when writing comparison code!!!
}
public static bool operator !=(MyType left, MyType right)
{
return !(left == right);
}
public bool Equals(MyType x, MyType y)
{
return (x == y);
}
public int GetHashCode(MyType obj)
{
return base.GetHashCode();
}
代码对应的框中包含两个整数,并比较装箱(=)生成的两个对象。此比较仅供参考
.locals init ([0] object val1,
[1] object val2,
[2] bool result1,
[3] bool result2)
IL_0000: nop
IL_0001: ldc.i4.1
IL_0002: box [mscorlib]System.Int32
IL_0007: stloc.0
IL_0008: ldc.i4.1
IL_0009: box [mscorlib]System.Int32
IL_000e: stloc.1
IL_000f: ldloc.0
IL_0010: ldloc.1
IL_0011: ceq
IL_0013: stloc.2
IL_0014: ldloc.0
IL_0015: ldloc.1
IL_0016: callvirt instance bool [mscorlib]System.Object::Equals(object)
IL_001b: stloc.3
对于.Equals,它调用Object.Equals,后者调用Int32.Equals(对对象的虚拟方法调用):
这将强制转换为int并将值作为整数进行比较,这是一种值类型比较。除非存在运算符重载。这似乎是唯一正确的答案(或者,至少,我非常确定您可以在字符串上使用==并使其按预期工作)。好的,我不明白为什么在这里使用Equals。根据文档,“Equals的默认实现支持引用类型的引用相等,值类型的位相等。引用相等意味着比较的对象引用引用同一个对象。”@John C:问得好。我的最新答案是否更清楚?是的,谢谢,现在有道理了。我假设对于您自己的用户定义类,您需要提供您自己的相等定义。假设它们相等,但两个不同的实例dude,==和.Equals做两件不同的事情操作员检查val1和val2是否占用相同的内存空间(参考)。Equals检查内容是否相等。您也可以使用对象。Equals(对象,对象)
静态方法,该方法首先尝试使用=
运算符比较对象,然后在两个参数均不为空时尝试对象。Equals(对象)
方法。我建议这样做的原因是,在调用object.Equals(object,object)
之前,您不必检查null,而在调用object.Equals(object)
时则需要检查null。