Эта статья является зеркальной статьёй машинного перевода, пожалуйста, нажмите здесь, чтобы перейти к оригиналу.

Вид: 3341|Ответ: 0

[Источник] .NET/C# новый тип записи функций

[Скопировать ссылку]
Опубликовано 02.10.2023 9:25:51 | | | |
Начиная с C# 9, вы можете использовать модификатор записи для определения типа ссылки, который предоставляет встроенную функциональность для инкапсуляции данных. C# 10 позволяет синтаксису класса записи в качестве синонима для уточнения типов ссылки и позволяет структуре записи определять типы значений с использованием той же функциональности.

Сценарии использования для записи в C#(ChatGPT отвечает):

Тип записи на C# — это новая функция, появившаяся в последней версии. Он может использоваться во многих случаях, включая, но не ограничиваясь, следующими:

Неизменяемый объект данных: тип записи неизменяем, то есть после создания значение его свойства нельзя изменить. Это делает их идеальными для представления неизменяемых структур данных, таких как объекты передачи (DTO) или настройки конфигурации.
Объекты значений: тип записи может использоваться для представления объектов стоимости, равенство которых определяется на основе значений атрибутов, а не эталонной эквивалентности. Это делает их идеальными для сравнения и хранения объектов значений, таких как диапазоны дат, точки координат и другие.
Сопоставление шаблонов: тип записи может использоваться вместе с сопоставлением шаблонов, что делает его более удобным при работе со сложными структурами данных. Вы можете использовать сопоставление шаблонов, чтобы проверить и извлечь значения атрибутов объекта записи, чтобы выполнить соответствующее действие.
Неизменяемые коллекции: тип записи может использоваться с неизменяемыми типами коллекций, такими как ImmutableList, ImmuttableDictionary и др., для создания неизменяемых объектов коллекции. Это гарантирует, что содержание коллекции не изменяется, тем самым повышая надёжность и безопасность кода.
Это лишь некоторые из сценариев использования типа записи, и вы можете решить, использовать ли этот тип записи, исходя из ваших конкретных потребностей и структуры кода.
Различие между записью и классом и структурой

Синтаксис, используемый при объявлении и создании класса или структуры, совпадает с записью операции. Просто замените ключевое слово класса на запись или используйте структуру записи вместо struct. Аналогично, класс записи поддерживает тот же синтаксис для наследования отношений. Различие между записью и классом следующее:

  • В основном конструкторе можно использовать позиционные параметры для создания и создания типов с неизменяемыми свойствами.
  • Методы и операторы, указывающие на равенство или неравенство в классах (например, Object.Equals(Object) и ==), указывают на равенство или неравенство значений в записи.
  • Вы можете использовать выражение with для создания копии неизменяемого объекта с новым значением в выбранном атрибуте.
  • Метод ToString записи создаёт строку формата, которая отображает имя типа объекта, а также имена и значения всех его общих свойств.
  • Запись может быть унаследована от другой. Но записи нельзя наследовать от классов, как и классы нельзя наследовать от записей.
  • Разница между структурой записи и структурой заключается в том, что компилятор синтезирует методы для определения равенства и ToString. Компилятор синтезирует метод Deconstruct для структуры записи позиции.


Компилятор синтезирует общее свойство только инициализации для каждого основного параметра конструктора в классе записи. В структуре записи компилятор синтезирует свойства публичного чтения/записи. Компилятор не создаёт свойства для основных аргументов конструктора в типах классов и структур, не содержащих модификатора записи.

запись

Тип ссылки на класс записи (по умолчанию: класс может быть опущен)
Тип значения структуры записи

Грамматика записи сахара

На самом деле это именно такСинтаксис, сахар, и конечный результат — код класса или структуры。 Возьмём следующий код в качестве примера:

В конце концов, он компилируется в следующий код:

используя System;
с использованием System.Collections.Generic;
с использованием System.Diagnostics;
с использованием System.Reflection;
с использованием System.Runtime.CompilerServices;
с использованием System.Security;
с использованием System.Security.Permissions;
с использованием System.Text;
с использованием Microsoft.CodeAnalysis;

[сборка: CompilationRelaxations(8)]
[ассемблер: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[ассемблер: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue | DebuggableAttribute.DebuggingModes.DisableOptimizations)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[сборка: AssemblyVersion("0.0.0.0")]
[модуль: UnverifiableCode]
[модуль: System.Runtime.CompilerServices.RefSafetyRules(11)]

[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
публичный класс PersonInfo : IEquatable<PersonInfo>
{
    [КомпиляторГенерировано]
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    k__BackingField для приватного чтения строк;<FirstName>

    [КомпиляторГенерировано]
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    k__BackingField для приватного чтения;<LastName>

    [КомпиляторГенерировано]
    защищённый виртуальный тип EqualityContract
    {
        [КомпиляторГенерировано]
        Получить
        {
            тип возврата (PersonInfo);
        }
    }

    публичная строка FirstName
    {
        [КомпиляторГенерировано]
        Получить
        {
            возвращение <FirstName>k__BackingField;
        }
        [КомпиляторГенерировано]
        init
        {
            <FirstName>k__BackingField = значение;
        }
    }

    публичная строка Фамилия
    {
        [КомпиляторГенерировано]
        Получить
        {
            <LastName>k__BackingField возврата;
        }
        [КомпиляторГенерировано]
        init
        {
            <LastName>k__BackingField = значение;
        }
    }

    публичный PersonInfo (строка Имя, строка Фамилия)
    {
        <FirstName>k__BackingField = Имя;
        <LastName>k__BackingField = Фамилия;
        основа.. ctor();
    }

    [КомпиляторГенерировано]
    публичная строка переопределения ToString()
    {
        StringBuilder stringBuilder = новый StringBuilder();
        stringBuilder.Append("PersonInfo");
        stringBuilder.Append(" { ");
        if (PrintMembers(stringBuilder))
        {
            stringBuilder.Append(' ');
        }
        stringBuilder.Append('}');
        return stringBuilder.ToString();
    }

    [КомпиляторГенерировано]
    Защищённый виртуальный bool PrintMembers (StringBuilder builder)
    {
        RuntimeHelpers.EnsureSufficientExecutionStack();
        строитель. Append("Имя = ");
        строитель. Append((object)FirstName);
        строитель. Append(", Фамилия = ");
        строитель. Append((object)LastName);
        вернитесь на истину;
    }

    [System.Runtime.CompilerServices.NullableContext(2)]
    [КомпиляторГенерировано]
    публичный статический оператор була !=(PersonInfo слева, PersonInfo справа)
    {
        возвращать! (слева == справа);
    }

    [System.Runtime.CompilerServices.NullableContext(2)]
    [КомпиляторГенерировано]
    публичный оператор статического буля ==(PersonInfo слева, PersonInfo справа)
    {
        return (object)left == right || ((object)left != null && left. Равно (справа));
    }

    [КомпиляторГенерировано]
    публичное переопределение int GetHashCode()
    {
        return (EqualityComparer<Type>. Default.GetHashCode(EqualityContract) * -1521134295 + EqualityComparer<string>. Default.GetHashCode(<FirstName>k__BackingField)) * -1521134295 + EqualityComparer<string>. Default.GetHashCode(<LastName>k__BackingField);
    }

    [System.Runtime.CompilerServices.NullableContext(2)]
    [КомпиляторГенерировано]
    public override bool Equals (object obj)
    {
        return Equals (obj как PersonInfo);
    }

    [System.Runtime.CompilerServices.NullableContext(2)]
    [КомпиляторГенерировано]
    публичный виртуальный bool Equals (PersonInfo другое)
    {
        return (object)this == другое || ((объект)другое!= null && EqualityContract == другое. EqualityContract и EqualityComparer<string>. По умолчанию. Равно (<FirstName>k__BackingField, другое<FirstName>. k__BackingField) && EqualityComparer<string>. По умолчанию. Equals(<LastName>k__BackingField, other.<LastName>k__BackingField));
    }

    [КомпиляторГенерировано]
    публичный виртуальный <Clone>PersonInfo $()
    {
        вернуть новый PersonInfo(это);
    }

    [КомпиляторГенерировано]
    Защищённая PersonInfo (оригинал PersonInfo)
    {
        <FirstName>k__BackingField = оригинал. <FirstName>k__BackingField;
        <LastName>k__BackingField = оригинал. <LastName>k__BackingField;
    }

    [КомпиляторГенерировано]
    public void Deconstruct (выходит строка FirstName, выходит строка LastName)
    {
        FirstName = это. FirstName;
        Фамилия = это. Фамилия;
    }
}

Пространство имён Microsoft.CodeAnalysis
{
    [КомпиляторГенерировано]
    [Встроено]
    внутренний запечатанный класс EmbeddedAttribute : Attribute
    {
    }
}

Namespace System.Runtime.CompilerServices
{
    [КомпиляторГенерировано]
    [Microsoft.CodeAnalysis.Embeddeded]
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenerricParameter, AllowMultiple = false, Inherited = false)]
    внутренний запечатанный класс NullableAttribute : Атрибут
    {
        публичный байт для чтения[] NullableFlags;

        public NullableAttribute(байт P_0)
        {
            byte[] array = новый байт[1];
            массив[0] = P_0;
            NullableFlags = массив;
        }

        public NullableAttribute(byte[] P_0)
        {
            NullableFlags = P_0;
        }
    }

    [КомпиляторГенерировано]
    [Microsoft.CodeAnalysis.Embeddeded]
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
    внутренний запечатанный класс NullableContextAttribute : Атрибут
    {
        общедоступный байт Flag;

        public NullableContextAttribute(byte P_0)
        {
            Флаг = P_0;
        }
    }

    [КомпиляторГенерировано]
    [Microsoft.CodeAnalysis.Embeddeded]
    [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
    внутренний запечатанный класс RefSafetyRulesАтрибут : Атрибут
    {
        общедоступная версия для чтения;

        публичный RefSafetyRulesAttribute(int P_0)
        {
            Версия = P_0;
        }
    }
}
Он автоматически генерирует конструкторы, переписывает методы ToString, GetHashCode, Equals и автоматически генерирует некоторые методы.


p1 и p2 на самом деле являются разными объектами, но поскольку компилятор автоматически генерировал компаратор (IEquatable) и переписывал методы Equals и GetHashCode, результат был верным. Вызов метода ToString также очень интуитивно понятен для вывода записанного значения. Как показано ниже:

.NET/C# реализует пользовательский компаратор IEqualityComparer
https://www.itsvse.com/thread-10643-1-1.html



запись

ОбязательноМодификатор :required указывает, что поле или атрибут, который он применяет, должно быть инициализовано всеми конструкторами или с использованием инициализатора объекта. Любое выражение, используемое для инициализации нового экземпляра этого типа, должно инициализировать все необходимые элементы.
Ссылка:Вход по гиперссылке виден.

init: В C#9 и более поздних версиях ключевое слово init определяет метод доступа в свойстве или индексаторе. Библиотека только для INIT присваивает значения только атрибутам или элементам индексатора во время построения объекта. Это обеспечивает неизменяемость, поэтому после инициализации объекта изменить его уже нельзя.
Ссылка:Вход по гиперссылке виден.

с: Если нужно воспроизвести экземпляр с некоторыми изменениями, можно использовать выражение with для реализации неразрушительных изменений. с выражением для создания нового экземпляра записи, который является копией существующего экземпляра записи, изменяя указанные свойства и поля.
Ссылка:Вход по гиперссылке виден.

Таким образом, запись можно определить следующим образом:

Обязательно, не говоря уже о своём синтаксисическом сахаре, это будетВызовите автоматически <Clone>сгенерированный метод $а затем изменять значение атрибута. Следующим образом:



Код:



Атрибут записи

Иногда нужно добавить некоторые функции в атрибуты, такие как функции сериализации JSON, описание и т.д.



Ресурсы:

Вход по гиперссылке виден.
Вход по гиперссылке виден.





Предыдущий:ASP.NET Core (24) основан на Refit, высокопроизводительной коммуникации MemoryPack
Следующий:GitHub использует REST API для просмотра размеров репозиториев
Отказ:
Всё программное обеспечение, программные материалы или статьи, публикуемые Code Farmer Network, предназначены исключительно для учебных и исследовательских целей; Вышеуказанный контент не должен использоваться в коммерческих или незаконных целях, иначе пользователи несут все последствия. Информация на этом сайте взята из Интернета, и споры по авторским правам не имеют отношения к этому сайту. Вы должны полностью удалить вышеуказанный контент с компьютера в течение 24 часов после загрузки. Если вам нравится программа, пожалуйста, поддержите подлинное программное обеспечение, купите регистрацию и получите лучшие подлинные услуги. Если есть нарушение, пожалуйста, свяжитесь с нами по электронной почте.

Mail To:help@itsvse.com