两个相同的.NET对象并不是说它们

时间:2010-08-12 17:00:32

标签: c# equals equality

我有以下代码:

object val1 = 1;
object val2 = 1;

bool result1 = (val1 == val2);//Equals false
bool result2 = val1.Equals(val2); //Equals true

这是怎么回事?解决这个问题的唯一方法是使用.Equals()方法吗?

7 个答案:

答案 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并将值作为整数进行比较,即值类型比较。

相关问题