I'm wondering how you could compare two boxed integers (either can be signed or unsigned) to each other for equality.
我想知道如何将两个被装箱的整数(可以是有符号的,也可以是无符号的)相互比较,使它们相等。
For instance, take a look at this scenario:
例如,看看这个场景:
// 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)
I'm stumped on how to reliably compare boxed integer types this way. I won't know what they are until runtime, and I can't just cast them both to long
, because one could be a ulong
. I also can't just convert them both to ulong
because one could be negative.
我对如何以这种方式可靠地比较装箱整数类型感到困惑。直到运行时我才知道它们是什么,我不能把它们都转换成长时间,因为一个可能是ulong。我也不能把它们都转换成ulong因为一个可以是负的。
The best idea I could come up with is to just trial-and-error-cast until I can find a common type or can rule out that they're not equal, which isn't an ideal solution.
我能想到的最好的办法就是试错,直到我找到一个通用类型或者排除它们不相等的可能性,这不是一个理想的解决方案。
2 个解决方案
#1
35
In case 2, you actually end up calling int.Equals(int)
, because ushort
is implicitly convertible to int
. This overload resolution is performed at compile-time. It's not available in case 3 because the compiler only knows the type of int5
and int6
as object
, so it calls object.Equals(object)
... and it's natural that object.Equals
will return false
if the types of the two objects are different.
在情形2中,您最终调用int. equals (int),因为ushort可以隐式转换为int.这个重载解析在编译时执行。在情形3中不可用,因为编译器只知道int5和int6作为对象的类型,所以它调用object. equals (object)…这个物体很自然。如果两个对象的类型不同,Equals将返回false。
You could use dynamic typing to perform the same sort of overload resolution at execution time - but you'd still have a problem if you tried something like:
您可以使用动态类型在执行时执行相同的重载解析——但是如果您尝试以下方法,您仍然会遇到问题:
dynamic x = 10;
dynamic y = (long) 10;
Console.WriteLine(x.Equals(y)); // False
Here there's no overload that will handle long
, so it will call the normal object.Equals
.
这里没有处理长数据的重载,因此它将调用normal object.Equals。
One option is to convert the values to decimal
:
一种方法是将值转换为decimal:
object x = (int) 10;
object y = (long) 10;
decimal xd = Convert.ToDecimal(x);
decimal yd = Convert.ToDecimal(y);
Console.WriteLine(xd == yd);
This will handle comparing ulong
with long
as well.
这也将处理长龙的比较。
I've chosen decimal
as it can exactly represent every value of every primitive integer type.
我选择了decimal,因为它可以精确地表示每个基本整数类型的每个值。
#2
0
Integer is a value type. When you compare two integers types, compiller checks their values.
Integer是一种值类型。当比较两个整数类型时,compiller检查它们的值。
Object is a reference type. When you compare two objects, compiller checks their references.
对象是引用类型。当您比较两个对象时,compiller会检查它们的引用。
The interesting part is here:
有趣的是:
object int5 = (int)50505;
Compiller perfoms boxing operation, wraps value type into reference type, and Equals
will compare references, not values.
Compiller perfoms装箱操作,将值类型包装为引用类型,并且Equals将比较引用,而不是值。
#1
35
In case 2, you actually end up calling int.Equals(int)
, because ushort
is implicitly convertible to int
. This overload resolution is performed at compile-time. It's not available in case 3 because the compiler only knows the type of int5
and int6
as object
, so it calls object.Equals(object)
... and it's natural that object.Equals
will return false
if the types of the two objects are different.
在情形2中,您最终调用int. equals (int),因为ushort可以隐式转换为int.这个重载解析在编译时执行。在情形3中不可用,因为编译器只知道int5和int6作为对象的类型,所以它调用object. equals (object)…这个物体很自然。如果两个对象的类型不同,Equals将返回false。
You could use dynamic typing to perform the same sort of overload resolution at execution time - but you'd still have a problem if you tried something like:
您可以使用动态类型在执行时执行相同的重载解析——但是如果您尝试以下方法,您仍然会遇到问题:
dynamic x = 10;
dynamic y = (long) 10;
Console.WriteLine(x.Equals(y)); // False
Here there's no overload that will handle long
, so it will call the normal object.Equals
.
这里没有处理长数据的重载,因此它将调用normal object.Equals。
One option is to convert the values to decimal
:
一种方法是将值转换为decimal:
object x = (int) 10;
object y = (long) 10;
decimal xd = Convert.ToDecimal(x);
decimal yd = Convert.ToDecimal(y);
Console.WriteLine(xd == yd);
This will handle comparing ulong
with long
as well.
这也将处理长龙的比较。
I've chosen decimal
as it can exactly represent every value of every primitive integer type.
我选择了decimal,因为它可以精确地表示每个基本整数类型的每个值。
#2
0
Integer is a value type. When you compare two integers types, compiller checks their values.
Integer是一种值类型。当比较两个整数类型时,compiller检查它们的值。
Object is a reference type. When you compare two objects, compiller checks their references.
对象是引用类型。当您比较两个对象时,compiller会检查它们的引用。
The interesting part is here:
有趣的是:
object int5 = (int)50505;
Compiller perfoms boxing operation, wraps value type into reference type, and Equals
will compare references, not values.
Compiller perfoms装箱操作,将值类型包装为引用类型,并且Equals将比较引用,而不是值。