两个相同的.NET对象并不是说它们
我有以下代码:
object val1 = 1; object val2 = 1; bool result1 = (val1 == val2);//Equals false bool result2 = val1.Equals(val2); //Equals true
那是怎么回事? 修复此问题的唯一方法是使用.Equals()方法吗?
operator ==
是静态的,而不是虚拟的,因此行为由静态类型而不是运行时类型决定。 对于引用类型的对象, ==
的默认实现是比较引用(尽管类型可以实现不同的行为,例如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
的实现一样。
是。 ==
检查参考相等性。 在要比较内容的位置使用Equals
。
你可能想知道为什么对象是这样的。 将整数(值类型)设置为对象变量时,会发生称为装箱的操作。 此操作将值类型包装到对象中,并将其放在堆上并返回引用。 这种情况发生两次,引用变得不同(尽管值相同)。
==
检查两个对象是否相同 。 他们不是。 它们代表相同的数字,但存储在内存中的不同位置。
这就像比较两个苹果。 两者都是苹果 ,看起来一样,但它们是不同的对象。
这是因为当你将它们转换为对象时,它们会被“转换”为对int值的引用。 而这两个参考文献并不相同。 但是equals比较引用的值而不是引用。
如果您不使用object
而是自定义类,则可以覆盖==和!=运算符,并且可能应该实现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(); }
如果两个对象指向内存中的相同空间,则它们是相等的。
val1 == val1; //Equals true
正如tc所指出的那样,您可以使运算符过载。
public static bool operator ==(Object a, Object b)
这样运算符==
的行为将是此方法定义的行为。
您还应该重载运算符!=
当您重载==
。
您的代码的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并将值作为整数进行比较,即值类型比较。