比较两个整数对象的相等性,无论类型如何

29
我想知道如何比较两个盒装整数(可以是带符号或无符号的)是否相等。
例如,看一下下面的情况:
// case #1
object int1 = (int)50505;
object int2 = (int)50505;
bool success12 = int1.Equals(int2); // this is true. (pass)

// case #2
int int3 = (int)50505;
ushort int4 = (ushort)50505;
bool success34 = int3.Equals(int4); // this is also true. (pass)

// case #3
object int5 = (int)50505;
object int6 = (ushort)50505;
bool success56 = int5.Equals(int6); // this is false. (fail)

我不知道如何可靠地比较装箱整数类型。在运行时,我不知道它们的具体类型,并且不能将它们都强制转换为long,因为其中一个可能是ulong。我也不能将它们都转换为ulong,因为其中一个可能为负数。

我能想到的最好的方法就是试错式地进行类型转换,直到找到共同的类型或排除它们不相等,但这不是理想的解决方法。


1
int3.Equals()实际上并不是重写的Equals,它是一个重载(Equals(int) vs Equals(object))。 - Rob
你的意思是“但是第三种情况失败了”吗? - Jon Skeet
2个回答

39
在情况2中,由于ushort可以隐式转换为int,您实际上会调用int.Equals(int)。这种重载解析是在编译时执行的。在情况3中不可用,因为编译器只知道int5int6的类型为object,所以它调用object.Equals(object)……如果两个对象的类型不同,object.Equals将返回false,这很自然。
可以使用动态类型来执行类似的重载解析,以便在执行时进行 - 但是如果您尝试执行以下操作,仍然会遇到问题:
dynamic x = 10;
dynamic y = (long) 10;
Console.WriteLine(x.Equals(y)); // False

这里没有重载可以处理long类型,所以会调用普通的object.Equals方法。

一个选项是将值转换为decimal类型:

object x = (int) 10;
object y = (long) 10;
decimal xd = Convert.ToDecimal(x);
decimal yd = Convert.ToDecimal(y);
Console.WriteLine(xd == yd);

这样可以处理ulonglong之间的比较。

我选择了decimal,因为它能精确地表示每个原始整数类型的值。


0

整数是一种value类型。当您比较两个整数类型时,编译器会检查它们的

对象是一种reference类型。当您比较两个对象时,编译器会检查它们的引用

有趣的部分在这里:

 object int5 = (int)50505; 

编译器执行装箱操作,将值类型包装成引用类型,Equals将比较引用而不是值。

5
根据问题中的措辞,我清楚知道值类型和引用类型之间的区别,这并没有回答问题,实际上。 - caesay

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接