Ответ 1
ValueType является специальным. Он делает это:
- Если obj по сравнению с null, оно возвращает false.
- Если аргументы этого и obj являются разными типами, он возвращает false.
- Он использует отражение для вызова Equals в каждом поле экземпляра для каждого значения, если любое из этих полей не равно, оно возвращает false. В противном случае он возвращает true, никогда не вызывая BaseTypes base.Equals(который является object.Equals).
Поскольку он использует отражение для сравнения полей, вы всегда должны переопределять Equals
на любом создаваемом ValueType
. Отражение происходит медленно.
Когда это "GCReference" или поле в структуре, которое является ссылочным типом, оно завершается с использованием отражения в каждом поле для сравнения. Он должен сделать это, потому что структура фактически имеет указатель на местоположение ссылочного типа в куче.
Если в структуре нет ссылочного типа, и они одного типа, поля гарантированно будут в одном порядке и будут иметь одинаковый размер в памяти, поэтому он может просто сравнить голую память.
Для структуры с только значениями типов для полей, т.е. структуры с только одним полем int
, во время сравнения не происходит никакого отражения. Ни одно из полей ничего не ссылается на кучу, поэтому нет GCReference
или GCHandle
. Кроме того, любой экземпляр этой структуры будет иметь одинаковое расположение в памяти полей (с несколькими незначительными исключениями), поэтому команда CLR может выполнить непосредственное сравнение памяти (memcmp), что намного быстрее, чем другая опция.
Итак, если у вас есть только типы значений в вашей структуре, он будет делать более быстрый memcmp вместо сравнения отражений, но вы, возможно, не захотите этого делать. Продолжайте читать.
Этот не означает означает, что вы должны использовать реализацию по умолчанию Equals
. На самом деле, не делайте этого. Прекрати это. Это делает бит-сравнения, которые не всегда точны. Что вы говорите? Позвольте мне показать вам:
private struct MyThing
{
public float MyFloat;
}
private static void Main(string[] args)
{
MyThing f, s;
f.MyFloat = 0.0f;
s.MyFloat = -0.0f;
Console.WriteLine(f.Equals(s)); // prints False
Console.WriteLine(0.0f == -0.0f); // prints True
}
Цифры равны математически, но они не равны в их двоичном представлении. Итак, я еще раз подчеркну, не полагается на стандартную реализацию ValueType.Equals