Сравните два целых объекта для равенства независимо от типа
Мне интересно, как вы могли бы сравнить два вложенных в квадрат целого числа (либо они могут быть подписаны, либо без знака) друг для друга для равенства.
Например, посмотрите на этот сценарий:
// 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
В случае 2 вы фактически вызываете int.Equals(int)
, потому что ushort
неявно конвертируется в int
. Это разрешение перегрузки выполняется во время компиляции. Он недоступен в случае 3, потому что компилятор знает только тип int5
и int6
как 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);
Это будет обрабатывать сравнение ulong
с long
.
Я выбрал decimal
, поскольку он может точно представлять каждое значение каждого примитивного целочисленного типа.
Ответ 2
Целое число - это значение. Когда вы сравниваете два типа целых чисел, компилятор проверяет их значения.
Объект - это ссылка. Когда вы сравниваете два объекта, компилятор проверяет их ссылки.
Интересная часть здесь:
object int5 = (int)50505;
Compiller выполняет бокс, переносит тип значения в ссылочный тип, а Equals
будет сравнивать ссылки, а не значения.