Подтвердить что ты не робот

Сравните два целых объекта для равенства независимо от типа

Мне интересно, как вы могли бы сравнить два вложенных в квадрат целого числа (либо они могут быть подписаны, либо без знака) друг для друга для равенства.

Например, посмотрите на этот сценарий:

// 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, потому что это может быть отрицательным.

Лучшая идея, которую я мог бы придумать, - просто пропустить пробную версию, пока я не смогу найти общий тип или не могу исключить, что они не равны, что не является идеальным решением.

4b9b3361

Ответ 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 будет сравнивать ссылки, а не значения.