Database
 sql >> база данни >  >> RDS >> Database

Сравняване на обекти по стойност. Част 6:Прилагане на структурното равенство

Вече анализирахме особеностите на структурите на .NET рамката, които представят Типове стойности при сравняване на обекти по стойност – екземпляр на структури.

Сега ще опиша този процес на конкретен пример, за да проверя дали ще ни позволи да определим използването на сравнението на обекти по стойност като цяло и по този начин да опростим извадка от сравняване на обекти по стойност – екземпляри на клас, които представляват референция видове.

Структурата на PersonStruct:

using System;

namespace HelloEquatable
{
    public struct PersonStruct : IEquatable<PersonStruct>, IEquatable<PersonStruct?>
    {
        private static int GetHashCodeHelper(int[] subCodes)
        {
            int result = subCodes[0];

            for (int i = 1; i < subCodes.Length; i++)
                result = unchecked(result * 397) ^ subCodes[i];

            return result;
        }

        private static string NormalizeName(string name) => name?.Trim() ?? string.Empty;

        private static DateTime? NormalizeDate(DateTime? date) => date?.Date;

        public string FirstName { get; }

        public string LastName { get; }

        public DateTime? BirthDate { get; }

        public PersonStruct(string firstName, string lastName, DateTime? birthDate)
        {
            this.FirstName = NormalizeName(firstName);
            this.LastName = NormalizeName(lastName);
            this.BirthDate = NormalizeDate(birthDate);
        }

        public override int GetHashCode() => GetHashCodeHelper(
            new int[]
            {
                this.FirstName.GetHashCode(),
                this.LastName.GetHashCode(),
                this.BirthDate.GetHashCode()
            }
        );

        public static bool Equals(PersonStruct first, PersonStruct second) =>
            first.BirthDate == second.BirthDate &&
            first.FirstName == second.FirstName &&
            first.LastName == second.LastName;

        public static bool operator ==(PersonStruct first, PersonStruct second) =>
            Equals(first, second);

        public static bool operator !=(PersonStruct first, PersonStruct second) =>
            !Equals(first, second);

        public bool Equals(PersonStruct other) =>
            Equals(this, other);

        public static bool Equals(PersonStruct? first, PersonStruct? second) =>
            first == second;
        // Alternate version:
        //public static bool Equals(PersonStruct? first, PersonStruct? second) =>
        //    first.HasValue == second.HasValue &&
        //    (
        //        !first.HasValue || Equals(first.Value, second.Value)
        //    );

        public bool Equals(PersonStruct? other) => this == other;
        // Alternate version:
        //public bool Equals(PersonStruct? other) =>
        //    other.HasValue && Equals(this, other.Value);

        public override bool Equals(object obj) =>
            (obj is PersonStruct) && Equals(this, (PersonStruct)obj);
        // Alternate version:
        //public override bool Equals(object obj) =>
        //    obj != null &&
        //    this.GetType() == obj.GetType() &&
        //    Equals(this, (PersonStruct)obj);
    }
}

Както можете да видите, този пример е по-малък и по-лесен по структура, тъй като екземпляри на структури не са нулеви и не е възможно да се наследяват от дефинирани от потребителя структури. Вече обсъдихме особеностите за прилагане на сравнението по стойност за екземплярите на класа в предишната ми статия.

Освен това сме определили полета за сравнение на обекти, както и внедрихме метода GetHashCode().

Методите и операторите за сравнение са имплементирани в следния ред:

  1. За да сравним два екземпляра на структури, ние внедрихме статичния метод PersonStruct.Equals(PersonStruct, PersonStruct). Ще използваме този метод като референтен метод за сравнение, когато прилагаме други методи и оператори. Освен това може да се приложи за сравняване на екземпляри на структури на езици, които не поддържат оператори.
  2. Операторите PersonStruct.==(PersonStruct, PersonStruct) и PersonStruct.!=(PersonStruct, PersonStruct) също са внедрени. Трябва да се отбележи, че C# компилаторът има следните особености:
  • Можете да сравните с претоварените оператори T.==(T, T) и T.!=(T, T) в Nullable(Of T)
  • Преди да провери равенството на стойностите, компилаторът може да провери дали екземпляри от структури имат валидна стойност. Освен това компилаторът не обвива екземпляри от структури в обекти.
  • По този начин, сравняването на екземпляри на структурата Nullable(Of T) с нетипизирана стойност с nullable води до извикване на операторите ==(T, T) или T.!=(T, T), като същевременно се сравняват екземпляри на Nullable( От T) структура без претоварени оператори T.==(T, T) и T.!=(T, T) води до извикване на операторите Object.==(Object, Object) или Object.!=(Object, Object) и в резултат на обвиване на екземпляр в обекта.
  1. Методът PersonStruct.Equals(PersonStruct) (внедряване на IEquatable(Of PersonStruct)) е реализиран чрез извикване на метода PersonStruct.Equals(PersonStruct, PersonStruct).
  2. За да избегнем обвиването на екземпляри от структури в обекти, когато имаме един или два екземпляра с Nullable(Of PersonStruct), е възможно да приложим следните методи:
  • PersonStruct.Equals(PersonStruct?, PersonStruct?), като извикване на оператора PersonStruct.==(PersonStruct, PersonStruct), се използва за избягване на обвиване на екземпляри от структури на двата аргумента в обекти и извикване на Object.Equals( Object, Object), ако поне един от аргументите е Nullable(Of PersonStruct) екземпляр. Освен това можете да използвате този метод за сравняване на екземпляри с Nullable(Of PersonStruct) на езици, които не поддържат оператори. В кода може да намерите коментари, обясняващи как този метод може да бъде приложен, ако компилаторът на C# не е в състояние да използва операторите T.==(T, T) и T.!=(T, T) за Nullable(Of Т) аргументи.
  • PersonStruct.Equals(PersonStruct?) – внедряването на интерфейса IEquatable(Of PersonStruct?), използван за избягване на обвиване на аргументите Nullable(Of PersonStruct) в обекти и извикване на метода PersonStruct.Equals(Object). Реализира се като извикване на оператора PersonStruct.==(PersonStruct, PersonStruct) с коментирания код за използване на оператори T.==(T, T) и T.!=(T, T) за Nullable(Of T) ) аргументи.
  • PersonStruct.Equals(Object) – който отменя метода Object.Equals(Object). Реализира се чрез проверка на съвместимостта на тип аргумент с тип на текущия обект, като се използва операторът is чрез прехвърляне на аргумента към PersonStruct и извикване на PersonStruct.Equals(PersonStruct, PersonStruct).

Бележки:

  • Имплементирането на интерфейса IEquatable(Of PersonStruct?) — IEquatable(Of Nullable(Of PersonStruct)) служи за показване на конкретни проблеми в платформата при работа със структури, при които обвиването на екземпляри в обекти става по-бързо, отколкото очакваме.
  • В реални проекти, при условие че не е необходимо да се подобрява производителността, внедряването на IEquatable(Of Nullable(Of T)) не е приложимо поради архитектурни причини – не трябва да внедряваме въведен IEquatable в типа T за нито един тип.
  • По принцип не е необходимо да се претоварва код с различни оптимизации.

За структурите бихме могли да постигнем да направим сравнението по стойност много по-просто и по-продуктивно, като избегнем наследяването на дефинирани от потребителя структури и необходимостта от проверка на обекти на null. Освен това можем да наблюдаваме нова логика, която поддържа аргументи с нула (Of T).

В бъдещата си публикация ще обобщя следните точки:

  • Когато е добра идея да се приложи сравнение на обекти по стойност;
  • Как можем да опростим прилагането на сравнение по стойност за обекти – екземпляри на клас, които представляват референтни типове.

Прочетете също:

Сравняване на обекти по стойност. Част 1:Начало

Сравняване на обекти по стойност. Част 2:Бележки за прилагане на метода Equals

Сравняване на обекти по стойност. Част 3:Специфични за типа оператори за равенство и равенство

Сравняване на обекти по стойност. Част 4:Оператори за наследяване и сравнение

Сравняване на обекти по стойност. Част 5:Проблем със структурното равенство


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Изпълнение на задачи за поддръжка на база данни на SQL с помощта на SQLCMD

  2. Проверка на състоянието на Exadata с помощта на Exachk Utility

  3. Разширено наблюдение и управление на бази данни за TimescaleDB

  4. Основи на паралелното програмиране с рамката Fork/Join в Java

  5. Създайте връзка в SQL