Compare two integer objects for equality regardless of type
Asked Answered
D

2

29

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.

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.

Disparity answered 26/1, 2016 at 6:48 Comment(3)
int3.Equals() is not actually the overriden Equals, it's an overload (Equals(int) vs Equals(object))Abacus
Do you mean "but case 3 fails"?Protean
Possible duplicate of Why does ((object)(int)1).Equals(((object)(ushort)1)) yield false?Kike
P
39

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.

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.

One option is to convert the values to 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.

Protean answered 26/1, 2016 at 6:59 Comment(0)
C
0

Integer is a value type. When you compare two integers types, compiller checks their values.

Object is a reference type. When you compare two objects, compiller checks their references.

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.

Codicil answered 26/1, 2016 at 7:9 Comment(1)
It should be clear by the wording in the question that I know the difference between value and reference types, this doesn't answer the question at all, actually.Disparity

© 2022 - 2024 — McMap. All rights reserved.