Почему этот код возвращает true:
new Byte() == new Byte() // returns true
но этот код возвращает false:
new Byte[0] == new Byte[0] // returns false
Почему этот код возвращает true:
new Byte() == new Byte() // returns true
но этот код возвращает false:
new Byte[0] == new Byte[0] // returns false
Потому что new Byte()
создает тип значения, который сравнивается по значению (по умолчанию он возвращает byte
со значением 0
). И new Byte[0]
создает массив, который является ссылочным типом и сравнивается по ссылке (и эти два экземпляра массива будут иметь разные ссылки).
Подробнее см. Типы значений и ссылочные типы.
Байты типы значений в .NET, что означает, что оператор ==
возвращает true тогда и только тогда, когда два байта имеют одинаковое значение, Это также называется равенство значений.
Но массивы типы ссылок в .NET, то есть оператор ==
возвращает true тогда и только тогда, когда они ссылаются на один и тот же экземпляр массива в памяти. Это также называется ссылочным равенством или идентификатором.
Обратите внимание, что оператор ==
может быть перегружен как для ссылочных, так и для значений. System.String
, например, является ссылочным типом, но оператор ==
для строк сравнивает каждый символ в массиве в последовательности. См. Рекомендации по перегрузке Equals() и оператора == (Руководство по программированию на С#).
Если вы хотите проверить, содержат ли массивы точно такие же значения (по порядку), вы должны использовать Enumerable.SequenceEqual
вместо ==
.
сравнение ссылки фактически сравнивает адрес указателя, которые являются разными, что является причиной, возвращающей значение false, а в значении значения не имеет значения, сравнивает значение.
Компилятор попытается сохранить тип значения в реестрах, но из-за ограниченного числа регистров дальнейшее хранение происходит в Stack со значениями [Reference], в то время как тип Reference находится в стеке, но значение сохраняется адрес адреса памяти в куче.
Сравнение здесь сравнивает значение, присутствующее в стеке, которое в первом случае одинаково, а во втором случае это адреса кучи, которые различны.
Существует перегрузка оператора ==
, в котором оба операнда имеют тип byte
, и он реализуется для сравнения значения каждого байта; в этом случае у вас есть два нулевых байта, и они равны.
Оператор ==
не перегружен для массивов, поэтому используется перегрузка с двумя операндами object
(поскольку массивы имеют тип object
) во втором случае, а в ее реализации сравниваются ссылки на два объекты. Ссылка на два массива отличается.
Стоит отметить, что это не имеет ничего (непосредственно) в том, что byte
- тип значения, а массивы - ссылочные типы. Оператор ==
для byte
имеет семантику значения только потому, что существует определенная перегрузка оператора с этой реализацией. Если эта перегрузка не существовала, то не было бы перегрузки, для которой два байта были бы допустимыми операндами, и как таковой код вообще не компилировался. Вы можете легко это увидеть, создав пользовательский struct
и сравнив два экземпляра его с оператором ==
. Код не будет компилироваться, если вы не предоставите собственную реализацию ==
для этих типов.