Почему эти два сравнения имеют разные результаты?

Почему этот код возвращает true:

new Byte() == new Byte()   // returns true

но этот код возвращает false:

new Byte[0] == new Byte[0] // returns false

Ответ 1

Потому что new Byte() создает тип значения, который сравнивается по значению (по умолчанию он возвращает byte со значением 0). И new Byte[0] создает массив, который является ссылочным типом и сравнивается по ссылке (и эти два экземпляра массива будут иметь разные ссылки).

Подробнее см. Типы значений и ссылочные типы.

Ответ 2

Байты типы значений в .NET, что означает, что оператор == возвращает true тогда и только тогда, когда два байта имеют одинаковое значение, Это также называется равенство значений.

Но массивы типы ссылок в .NET, то есть оператор == возвращает true тогда и только тогда, когда они ссылаются на один и тот же экземпляр массива в памяти. Это также называется ссылочным равенством или идентификатором.

Обратите внимание, что оператор == может быть перегружен как для ссылочных, так и для значений. System.String, например, является ссылочным типом, но оператор == для строк сравнивает каждый символ в массиве в последовательности. См. Рекомендации по перегрузке Equals() и оператора == (Руководство по программированию на С#).

Если вы хотите проверить, содержат ли массивы точно такие же значения (по порядку), вы должны использовать Enumerable.SequenceEqual вместо ==.

Ответ 3

сравнение ссылки фактически сравнивает адрес указателя, которые являются разными, что является причиной, возвращающей значение false, а в значении значения не имеет значения, сравнивает значение.

Компилятор попытается сохранить тип значения в реестрах, но из-за ограниченного числа регистров дальнейшее хранение происходит в Stack со значениями [Reference], в то время как тип Reference находится в стеке, но значение сохраняется адрес адреса памяти в куче.

Сравнение здесь сравнивает значение, присутствующее в стеке, которое в первом случае одинаково, а во втором случае это адреса кучи, которые различны.

reference

Ответ 4

Существует перегрузка оператора ==, в котором оба операнда имеют тип byte, и он реализуется для сравнения значения каждого байта; в этом случае у вас есть два нулевых байта, и они равны.

Оператор == не перегружен для массивов, поэтому используется перегрузка с двумя операндами object (поскольку массивы имеют тип object) во втором случае, а в ее реализации сравниваются ссылки на два объекты. Ссылка на два массива отличается.

Стоит отметить, что это не имеет ничего (непосредственно) в том, что byte - тип значения, а массивы - ссылочные типы. Оператор == для byte имеет семантику значения только потому, что существует определенная перегрузка оператора с этой реализацией. Если эта перегрузка не существовала, то не было бы перегрузки, для которой два байта были бы допустимыми операндами, и как таковой код вообще не компилировался. Вы можете легко это увидеть, создав пользовательский struct и сравнив два экземпляра его с оператором ==. Код не будет компилироваться, если вы не предоставите собственную реализацию == для этих типов.