Je me demande comment vous pourriez comparer deux entiers encadrés (qui peuvent être signés ou non signés) l'un à l'autre pour l'égalité.
Par exemple, jetez un œil à ce scénario:
// 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)
Je suis perplexe sur la façon de comparer de manière fiable les types d'entiers encadrés de cette façon. Je ne saurai pas ce qu'ils sont avant l'exécution, et je ne peux pas simplement les convertir tous les deux en long
, car l'un pourrait être un ulong
. Je ne peux pas non plus simplement les convertir tous les deux en ulong
parce que l'un pourrait être négatif.
La meilleure idée que j'ai pu trouver est de simplement lancer un essai et une erreur jusqu'à ce que je puisse trouver un type commun ou exclure qu'ils ne sont pas égaux, ce qui n'est pas une solution idéale.
Dans le cas 2, vous finissez par appeler int.Equals(int)
, car ushort
est implicitement convertible en int
. Cette résolution de surcharge est effectuée au moment de la compilation. Il n'est pas disponible dans le cas 3 car le compilateur ne connaît que le type de int5
Et int6
Comme object
, donc il appelle object.Equals(object)
... et c'est naturel que object.Equals
renverra false
si les types des deux objets sont différents.
Vous pourriez utiliser le typage dynamique pour effectuer le même type de résolution de surcharge au moment de l'exécution - mais vous auriez toujours un problème si vous essayiez quelque chose comme:
dynamic x = 10;
dynamic y = (long) 10;
Console.WriteLine(x.Equals(y)); // False
Ici, il n'y a pas de surcharge qui gérera long
, donc il appellera le object.Equals
Normal.
Une option consiste à convertir les valeurs en decimal
:
object x = (int) 10;
object y = (long) 10;
decimal xd = Convert.ToDecimal(x);
decimal yd = Convert.ToDecimal(y);
Console.WriteLine(xd == yd);
Cela gérera également la comparaison de ulong
avec long
.
J'ai choisi decimal
car il peut représenter exactement chaque valeur de chaque type entier primitif.
L'entier est un type valeur . Lorsque vous comparez deux types d'entiers, le compilateur vérifie leurs valeurs .
L'objet est de type référence . Lorsque vous comparez deux objets, le compilateur vérifie leurs références .
La partie intéressante est ici:
object int5 = (int)50505;
Compiler perfoms boxing operation, encapsule le type de valeur dans le type de référence, et Equals
comparera les références, pas les valeurs.