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

В .NET 4.0, Какова стандартная реализация Equals для типов значений?

Кажется, что две страницы документации противоречат этой теме:

  • ValueType.Equals Method говорит: "По умолчанию метод Equals использует отражение для сравнения соответствующих полей obj и этого экземпляра."
  • Object.Equals Method (Object) говорит: "Стандартная реализация Equals поддерживает ссылочное равенство для ссылочных типов и побитовое равенство для типов значений".

Итак, это поразрядное равенство или отражение?

Я взглянул на исходный код ValueType и нашел комментарий, говорящий

//если в этом объекте нет ссылок GC, мы можем избежать отражения

//и выполните быстрый memcmp

Может ли кто-нибудь уточнить, что означает "ссылка GC"? Я думаю, это поле, имеющее ссылочный тип, но я не уверен.

Если я создаю struct, который имеет только поля типа значения, будут ли экземпляры его всегда сравнивать быстрый способ?

ОБНОВЛЕНИЕ: Документация for.Net 4.5 значительно улучшена: она свободна от указанного противоречия и теперь дает лучшее представление о том, как работает проверка соответствия типов по умолчанию.

4b9b3361

Ответ 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

Ответ 2

Не будучи настоящим экспертом в этой области, я бы просто пошел вперед и поставил свои мысли: В документации (по мне) указано, что если ваша структура имеет поле, являющееся объектом (ссылочным типом), отражение не может.

Итак, если у вас есть следующее:

    public struct SomeStruct
    {
        public object ObjectTest
    }

Объектный тест нельзя сравнивать без отражения. Так будет использоваться отражение. Эта часть текста, кажется, говорит, что я прав:

" ValueType.Equals. По умолчанию метод Equals использует отражение для сравнения соответствующих полей obj и этого экземпляра.