我有以下代码:
object val1 = 1;
object val2 = 1;
bool result1 = (val1 == val2);//Equals false
bool result2 = val1.Equals(val2); //Equals true
这是怎么回事?解决这个问题的唯一方法是使用.Equals()方法吗?
答案 0 :(得分:33)
运算符==
是静态的,而不是虚拟的,因此行为由静态类型而不是运行时类型决定。 ==
对引用类型对象的默认实现是比较引用(尽管类型可以实现不同的行为,例如string
)。您有两个不同的对象,它们没有相同的引用,因此==
返回false。
正如您所指出的,解决方案是使用Equals。 Equals是一种虚拟方法。由于value1
的运行时类型为Int32
,因此您最终会调用Int32.Equals。从.NET Reflector可以看到,它的实现如下:
public override bool Equals(object obj)
{
return ((obj is int) && (this == ((int) obj)));
}
换句话说,它检查参数是否为int
类型,如果是,则将其强制转换并使用为==
定义的int
。这比较了整数的值。
解决这个问题的唯一方法是使用.Equals()方法吗?
另一种方法是将对象转换为int
,然后使用==
,就像Int32.Equals
的实现一样。
答案 1 :(得分:10)
是。 ==
检查引用相等性。使用Equals
来比较内容。
您可能想知道为什么对象会如此。将整数(值类型)设置为对象变量时,会发生称为装箱的操作。此操作将值类型包装到对象中,并将其放在堆上并返回引用。这种情况发生两次,引用变得不同(尽管值相同)。
答案 2 :(得分:2)
==
检查两个对象是否相同。他们不是。它们代表相同的数字,但存储在内存中的不同位置。
这就像比较两个苹果。两者都是 apples 并且外观相同,但它们是不同的对象。
答案 3 :(得分:1)
这是因为当你将它们转换为对象时,它们被“转换”为对int值的引用。而这两个参考文献并不相同。 但是equals会比较引用的值而不是引用值。
答案 4 :(得分:0)
如果两个对象指向内存中的相同空间,则它们是相等的。
val1 == val1; //Equals true
正如tc所指出的,你可以让操作员过载。
public static bool operator ==(Object a, Object b)
这样,运算符==
的行为将是此方法定义的行为。
当您重载!=
时,您还应该重载运算符==
。
答案 5 :(得分:0)
如果您没有使用object
而是使用自定义类,则可以覆盖==和!=运算符,并且可能应该实现IEqualityComparer<T>
接口
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();
}
答案 6 :(得分:0)
代码框的CIL为两个整数,并比较装箱产生的两个对象(==)。这种比较是参考。
.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(对象上的虚方法调用):
public override bool Equals(object obj)
{
return ((obj is int) && (this == ((int) obj)));
}
这会转换为int并将值作为整数进行比较,即值类型比较。