À partir de C# 9, vous pouvez utiliser le modificateur d’enregistrement pour définir un type de référence qui offre une fonctionnalité intégrée pour encapsuler les données. C# 10 permet la syntaxe de la classe d’enregistrement comme synonyme pour clarifier les types de référence, et permet à la structure d’enregistrement de définir des types de valeur en utilisant la même fonctionnalité.
Cas d’utilisation pour l’enregistrement en C#(ChatGPT répond) :
Le type d’enregistrement en C# est une nouvelle fonctionnalité introduite dans la dernière version. Il peut être utilisé dans de nombreux scénarios, notamment mais sans s’y limiter :
Objet de données immuable : Le type d’enregistrement est immuable, ce qui signifie qu’une fois créé, sa valeur de propriété ne peut pas être modifiée. Cela les rend idéaux pour représenter des structures de données immuables telles que les objets de transfert (DTO) ou les paramètres de configuration. Objets valeur : Le type d’enregistrement peut être utilisé pour représenter des objets valeur dont l’égalité est déterminée en fonction de leurs valeurs d’attributs plutôt que de l’équivalence de référence. Cela les rend idéaux pour comparer et stocker des objets de valeur tels que les plages de dates, les points de coordonnées, et plus encore. Correspondance de motifs : Le type d’enregistrement peut être utilisé en conjonction avec la correspondance de motifs, ce qui le rend plus pratique lors du travail avec des structures de données complexes. Vous pouvez utiliser la correspondance de motifs pour vérifier et extraire les valeurs d’attribut de l’objet enregistrement afin d’effectuer l’action appropriée. Collections immutables : Le type d’enregistrement peut être utilisé avec des types de collections immutables tels que ImmutableList, ImmutableDictionary, etc., pour créer des objets de collection immuables. Cela garantit que le contenu de la collection n’est pas modifié, améliorant ainsi la fiabilité et la sécurité du code. Ce ne sont là que quelques-uns des cas d’utilisation du type d’enregistrement, et vous pouvez décider d’utiliser ce type en fonction de vos besoins spécifiques et de la structure de votre code. Différence entre disque et classe et structure
La syntaxe utilisée lors de la déclaration et de l’instanciation d’une classe ou d’une structure est la même que lors de l’enregistrement d’une opération. Il suffit de remplacer le mot-clé class par record, ou d’utiliser record struct au lieu de struct. De même, la classe d’enregistrement supporte la même syntaxe pour les relations d’héritage. La différence entre un enregistrement et une classe est la suivante :
- Vous pouvez utiliser des paramètres de position dans le constructeur principal pour créer et instancier des types aux propriétés immuables.
- Les méthodes et opérateurs qui indiquent l’égalité ou la non-égalité de référence dans les classes (par exemple, Object.Equals(Object) et ==) indiquent l’égalité ou la non-égalité de valeur dans l’enregistrement.
- Vous pouvez utiliser l’expression avec pour créer une copie d’un objet immuable avec une nouvelle valeur dans l’attribut sélectionné.
- La méthode ToString de l’enregistrement crée une chaîne de formats qui affiche le nom de type de l’objet ainsi que les noms et valeurs de toutes ses propriétés communes.
- Un dossier peut être hérité d’un autre registre. Mais les archives ne peuvent pas être héritées des classes, ni les classes héritées des archives.
- La différence entre la structure de l’enregistrement et la structure est que le compilateur synthétise des méthodes pour déterminer l’égalité et ToString. Le compilateur synthétise la méthode de déconstruction pour la structure de l’enregistrement de position.
Le compilateur synthétise une propriété commune d’initialisation uniquement pour chaque paramètre principal du constructeur dans la classe d’enregistrement. Dans une structure d’enregistrement, le compilateur synthétise les propriétés publiques de lecture/écriture. Le compilateur ne crée pas de propriétés pour les arguments principaux du constructeur dans les types de classes et de structures qui ne contiennent pas le modificateur d’enregistrement.
enregistrer
Type de référence de classe d’enregistrement (par défaut : la classe peut être omise) Type de valeur de structure d’enregistrement
Enregistrer le sucre de grammaire
Le record est en fait queSyntaxe sucre, et le résultat final est le code de classe ou de structure。 Prenons le code suivant comme exemple :
Enfin, il compile dans le code suivant :
utilisant System ; utilisant System.Collections.Generic ; en utilisant System.Diagnostics ; utilisant System.Reflection ; utilisant System.Runtime.CompilerServices ; en utilisant System.Security ; en utilisant System.Security.Permissions ; en utilisant System.Text ; en utilisant Microsoft.CodeAnalysis ;
[assemblage : CompilationRelaxations(8)] [assemblage : RuntimeCompatibility(WrapNonExceptionThrows = true)] [assemblage : Déboguable(DebuggableAttribute.DebuggableModes.Default | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue | DebuggableAttribute.DebuggingModes.DisableOptimizations)] [assemblage : SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assemblage : AssemblyVersion(« 0.0.0.0 »)] [module : Code-Invérifiable] [module : System.Runtime.CompilerServices.RefSafetyRules(11)]
[System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] Classe publique PersonInfo : IEquatable<PersonInfo>
{ [CompilateurGénéré] [DéboguerBrowsable(DebuggerBrowsableState.Jamais)] k__BackingField de chaîne de lecture <FirstName>privée ;
[CompilateurGénéré] [DéboguerBrowsable(DebuggerBrowsableState.Jamais)] k__BackingField de chaîne de lecture <LastName>privée ;
[CompilateurGénéré] Contrat d’Égalité de Type virtuel protégé { [CompilateurGénéré] Avoir { return typeof(PersonInfo) ; } }
chaîne publique Prénom { [CompilateurGénéré] Avoir { retour <FirstName>k__BackingField ; } [CompilateurGénéré] Init { <FirstName>k__BackingField = valeur ; } }
chaîne publique Nom de famille { [CompilateurGénéré] Avoir { retour <LastName>k__BackingField ; } [CompilateurGénéré] Init { <LastName>k__BackingField = valeur ; } }
public PersonInfo(chaîne Prénom, chaîne NomNom) { <FirstName>k__BackingField = Prénom ; <LastName>k__BackingField = NomDeNom ; base.. ctor() ; }
[CompilateurGénéré] chaîne d’override publique ToString() { StringBuilder chaenConstructeur = nouveau StringBuilder() ; stringBuilder.Append(« PersonInfo ») ; stringBuilder.Append( » { « ) ; if (PrintMembers(stringBuilder)) { stringBuilder.Append(' ') ; } stringBuilder.Append('}') ; return stringBuilder.ToString() ; }
[CompilateurGénéré] Bool virtuel protégé PrintMembers(StringBuilder builder) { RuntimeHelpers.EnsureSufficientExecutionStack() ; constructeur. Appender(« Prénom = « ) ; constructeur. Ajouter((objet)Prénom) ; constructeur. Append(« , Nom de famille = « ) ; constructeur. Ajouter((objet)NomDeNom) ; retour fidèle ; }
[System.Runtime.CompilerServices.NullableContext(2)] [CompilateurGénéré] opérateur de bool statique public !=(PersonInfo gauche, PersonInfo à droite) { rendre! (gauche == droite) ; }
[System.Runtime.CompilerServices.NullableContext(2)] [CompilateurGénéré] opérateur de bool statique public ==(PersonInfo à gauche, PersonInfo à droite) { return (object)left == droite || ((objet)left != null & & left. Égal (droite) ; }
[CompilateurGénéré] public override int GetHashCode() { return (EqualityComparer<Type>. Par défaut.GetHashCode(EqualityContract) * -1521134295 + EqualityComparer<string>. Par défaut.GetHashCode(<FirstName>k__BackingField)) * -1521134295 + <string>EqualityComparer. Par défaut.GetHashCode(<LastName>k__BackingField) ; }
[System.Runtime.CompilerServices.NullableContext(2)] [CompilateurGénéré] public override bool Equals(object obj) { retourner Equals(obj comme PersonInfo) ; }
[System.Runtime.CompilerServices.NullableContext(2)] [CompilateurGénéré] bool public virtuel égal (PersonInfo autre) { return (object)this == autres || ((objet)autre != null && EqualityContract == autre. EqualityContract & <string>EqualityComparer. Par défaut. Égal à <FirstName>k__BackingField, autre.<FirstName>k__BackingField) & <string>EqualityComparer. Par défaut. Égal (<LastName>k__BackingField, autre.<LastName>k__BackingField)) ; }
[CompilateurGénéré] PersonInfo public et <Clone>virtuel $() { return new PersonInfo (this) ; }
[CompilateurGénéré] PersonInfo protégé (PersonInfo original) { <FirstName>k__BackingField = original. <FirstName>k__BackingField ; <LastName>k__BackingField = original. <LastName>k__BackingField ; }
[CompilateurGénéré] public void Deconstruire (chaîne sortie Prénom, chaîne sortie NomNom) { Prénom = ceci. Prénom ; Nom de famille = ceci. Nom de famille ; }
}
Espace de noms Microsoft.CodeAnalysis
{ [CompilateurGénéré] [Intégré] classe interne scellée EmbeddedAttribute : Attribute { }
}
Espace de noms System.Runtime.CompilerServices
{ [CompilateurGénéré] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Propriété | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Paramètre | AttributeTargets.ReturnValue | AttributeTargets.Paramètre générique, PermettMultiple = faux, Hérité = faux)] classe interne scellée NullableAttribute : Attribut { octet public readonly[] NullableFlags ;
public NullableAttribute(byte P_0) { Byte[] tableau = nouvel octet[1] ; tableau[0] = P_0 ; NullableFlags = tableau ; }
public NullableAttribute(byte[] P_0) { NullableFlags = P_0 ; } }
[CompilateurGénéré] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delege, AllowMultiple = false, Inherited = false)] classe interne scellée NullableContextAttribute : Attribute { Drapeau de l’octet public readonly ;
public NullableContextAttribute(byte P_0) { Drapeau = P_0 ; } }
[CompilateurGénéré] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] classe interne scellée RefSafetyRulesAttribute : Attribut { version publique en lecture seule en version int ;
public RefSafetyRulesAttribute(int P_0) { Version = P_0 ; } }
} Il génère automatiquement des constructeurs, réécrit les méthodes ToString, GetHashCode, Equals, et génère automatiquement certaines méthodes.
p1 et p2 sont en réalité deux objets différents, mais comme le compilateur générait automatiquement le comparateur (IEquatable) et réécrivait les méthodes Equals et GetHashCode, la sortie était vraie. Appeler la méthode ToString est également très intuitif pour produire la valeur enregistrée. Comme montré ci-dessous :
enregistrer
Obligatoire:required indique que le champ ou l’attribut qu’il applique doit être initialisé par tous les constructeurs ou en utilisant l’initialiseur d’objet. Toute expression utilisée pour initialiser une nouvelle instance de ce type doit initialiser tous les membres requis. Référence:La connexion hyperlientérée est visible.
Init: En C# 9 et ultérieures, le mot-clé init définit la méthode d’accesseur dans une propriété ou un indexeur. La bibliothèque init uniquement attribue des valeurs uniquement aux attributs ou aux éléments de l’indexeur lors de la construction des objets. Cela impose l’immutabilité, donc une fois qu’un objet est initialisé, il ne peut plus être modifié. Référence:La connexion hyperlientérée est visible.
avec: Si vous devez répliquer une instance avec quelques modifications, vous pouvez utiliser l’expression avec pour implémenter des modifications non destructives. avec expression pour créer une nouvelle instance d’enregistrement qui est une copie d’une instance d’enregistrement existante, en modifiant les propriétés et champs spécifiés. Référence:La connexion hyperlientérée est visible.
Ainsi, l’enregistrement peut être défini comme suit :
Nécessaire, non, sans parler du fait qu’avec est en fait le sucre syntaxique, il le feraAppelez la méthode $ générée automatiquement <Clone>puis modifier la valeur de l’attribut. Comme suit:
Code:
Attribut du record
Parfois, il faut ajouter certaines fonctionnalités aux attributs, comme des caractéristiques de sérialisation JSON, des informations de description, etc.
Ressources:
La connexion hyperlientérée est visible.
La connexion hyperlientérée est visible.
|