|
|
Geplaatst op 02-10-2023 09:25:51
|
|
|
|

Vanaf C# 9 kun je de recordmodifier gebruiken om een referentietype te definiëren dat ingebouwde functionaliteit biedt voor het inkapselen van data. C# 10 maakt de recordklassesyntaxis als synoniem mogelijk om referentietypes te verduidelijken, en staat recordstructuur toe om waardetypes te definiëren met dezelfde functionaliteit.
Use cases voor record in C#(ChatGPT antwoordt):
Het recordtype in C# is een nieuwe functie die in de nieuwste versie is geïntroduceerd. Het kan in veel scenario's worden gebruikt, waaronder maar niet beperkt tot de volgende:
Onveranderlijk dataobject: Het recordtype is onveranderlijk, wat betekent dat eenmaal aangemaakt, de eigenschapswaarde niet kan worden gewijzigd. Dit maakt ze ideaal voor het representeren van onveranderlijke datastructuren zoals transfer objects (DTO's) of configuratie-instellingen. Waardeobjecten: Het recordtype kan worden gebruikt om waardeobjecten te representeren waarvan de gelijkheid wordt bepaald op basis van hun attribuutwaarden in plaats van referentie-equivalentie. Dit maakt ze ideaal voor het vergelijken en opslaan van waardeobjecten zoals datumbereiken, coördinatenpunten en meer. Patroonmatching: Het recordtype kan worden gebruikt in combinatie met patroonmatching, wat het handiger maakt bij het werken met complexe datastructuren. Je kunt patroonherkenning gebruiken om de attribuutwaarden van het recordobject te controleren en te extraheren, zodat je de juiste actie kunt uitvoeren. Onveranderlijke verzamelingen: Het recordtype kan worden gebruikt met onveranderlijke verzamelingstypen zoals ImmutableList, ImmutableDictionary, enzovoort, om onveranderlijke verzamelobjecten te creëren. Dit zorgt ervoor dat de inhoud van de collectie niet wordt aangepast, waardoor de betrouwbaarheid en veiligheid van de code verbeteren. Dit zijn slechts enkele van de gebruiksgevallen voor het recordtype, en je kunt beslissen of je het recordtype wilt gebruiken op basis van je specifieke behoeften en codestructuur. Verschil tussen record en class en struct
De syntaxis die wordt gebruikt bij het declareren en instansiëren van een klasse of structuur is hetzelfde als bij het opnemen van een bewerking. Vervang gewoon het class-keyword door record, of gebruik record struct in plaats van struct. Evenzo ondersteunt de recordklasse dezelfde syntaxis voor erfrelaties. Het verschil tussen een record en een klasse is als volgt:
- Je kunt positionele parameters in de hoofdconstructor gebruiken om types met onveranderlijke eigenschappen te creëren en te instantiëren.
- Methoden en operatoren die referentiegelijkheid of niet-gelijkheid in klassen aangeven (bijv. Object.Equals(Object) en ==) geven waardegelijkheid of niet-gelijkheid aan in het record.
- Je kunt de with-expressie gebruiken om een kopie te maken van een onveranderlijk object met een nieuwe waarde in het geselecteerde attribuut.
- De ToString-methode van het record creëert een formaatstring die de typenaam van het object en de namen en waarden van alle veelvoorkomende eigenschappen weergeeft.
- Een record kan worden geërfd van een ander record. Maar records kunnen niet worden geërfd van klassen, noch kunnen klassen worden geërfd van records.
- Het verschil tussen de recordstructuur en de structuur is dat de compiler methoden synthesizeert om gelijkheid en ToString te bepalen. De compiler synthetiseert de Deconstruct-methode voor de positierecordstructuur.
De compiler synthetiseert een gemeenschappelijke initialisatie-only eigenschap voor elke hoofdconstructorparameter in de recordklasse. In een recordstructuur synthetiseert de compiler publieke lees-/schrijfeigenschappen. De compiler maakt geen eigenschappen aan voor de hoofdconstructorargumenten in klasse- en structtypes die de recordmodifier niet bevatten.
record
Referentietype recordklasse (standaard: klasse kan worden weggelaten) Record structwaardetype
record grammar suiker
Record is eigenlijk datSyntaxis suiker, en het eindresultaat is class- of structcode。 Neem de volgende code als voorbeeld:
Ten slotte compileert het naar de volgende code:
met behulp van System; met behulp van System.Collections.Generic; gebruikmakend van System.Diagnostics; met behulp van System.Reflection; gebruik van System.Runtime.CompilerServices; gebruik van System.Security; gebruik van System.Security.Permissions; gebruik van System.Text; gebruik van Microsoft.CodeAnalysis;
[assemblage: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = waar)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribuut.DebuggingModes.EnableEditAndContinue | DebuggableAttribute.DebuggingModes.DisableOptimizations)] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assemblage: AssemblyVersion("0.0.0.0")] [module: Onverifieerbare Code] [module: System.Runtime.CompilerServices.RefSafetyRules(11)]
[System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] publieke klasse PersonInfo : IEkwalitatief<PersonInfo>
{ [CompilerGenerated] [DebuggerBrowsable(DebuggerBrowsableState.Never)] privé-readonly string <FirstName>k__BackingField;
[CompilerGenerated] [DebuggerBrowsable(DebuggerBrowsableState.Never)] private readonly string <LastName>k__BackingField;
[CompilerGenerated] beschermde virtuele Type Gelijkheidscontract { [CompilerGenerated] Toevoegen { return typeof(PersonInfo); } }
publieke string FirstName { [CompilerGenerated] Toevoegen { Geef <FirstName>k__BackingField terug; } [CompilerGenerated] Init { <FirstName>k__BackingField = waarde; } }
publieke string Achternaam { [CompilerGenerated] Toevoegen { keer <LastName>terug k__BackingField; } [CompilerGenerated] Init { <LastName>k__BackingField = waarde; } }
publieke PersonInfo(string FirstName, string LastName) { <FirstName>k__BackingField = Voornaam; <LastName>k__BackingField = Achternaam; base.. ctor(); }
[CompilerGenerated] publieke override-string ToString() { StringBuilder stringBuilder = nieuwe StringBuilder(); stringBuilder.Append("PersonInfo"); stringBuilder.Append(" { "); if (PrintMembers(stringBuilder)) { stringBuilder.Append(' '); } stringBuilder.Append('}'); return stringBuilder.ToString(); }
[CompilerGenerated] beschermde virtuele bool PrintMembers (StringBuilder builder) { RuntimeHelpers.EnsureSufficientExecutionStack(); bouwer. Append("FirstName = "); bouwer. Append((object)FirstName); bouwer. Append(", Achternaam = "); bouwer. Append((object)Achternaam); return true; }
[System.Runtime.CompilerServices.NullableContext(2)] [CompilerGenerated] publieke statische bool operator !=(PersonInfo links, PersonInfo rechts) { terugkeren! (links == rechts); }
[System.Runtime.CompilerServices.NullableContext(2)] [CompilerGenerated] publieke statische bool operator ==(PersonInfo links, PersonInfo rechts) { return (object)links == rechts || ((object)links != null && links. Gelijk (rechts); }
[CompilerGenerated] publieke override 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)] [CompilerGenerated] publieke override bool Gelijk (object obj) { Gelijken terug (obj als PersonInfo); }
[System.Runtime.CompilerServices.NullableContext(2)] [CompilerGenerated] publieke virtuele bool Gelijken (PersonInfo overig) { return (object)dit == overig || ((object)overig != null && EqualityContract == other. Gelijkheidscontract & Gelijkheidsvergelijker<string>. Default.Gelijk aan <FirstName>(k__BackingField, overige.<FirstName>k__BackingField) & EqualityComparer<string>. Default.Gelijk aan (<LastName>k__BackingField, overige.<LastName>k__BackingField)); }
[CompilerGenerated] publieke virtuele PersonInfo <Clone>$() { geef nieuwe PersonInfo(deze) terug; }
[CompilerGenerated] beschermde PersonInfo (PersonInfo origineel) { <FirstName>k__BackingField = origineel. <FirstName>k__BackingField; <LastName>k__BackingField = origineel. <LastName>k__BackingField; }
[CompilerGenerated] public void Deconstruct (uit string FirstName, out string LastName) { FirstName = dit. Voornaam; Achternaam = dit. Achternaam; }
}
naamruimte Microsoft.CodeAnalysis
{ [CompilerGenerated] [Ingebed] interne gesloten klasse EmbeddedAttribute : Attribuut { }
}
namespace System.Runtime.CompilerServices
{ [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttribuutDoelen.Gebeurtenis | AttribuutDoelen.Parameter | AttribuutDoelen.ReturnWaarde | AttribuutDoelen.GenericParameter, AllowMultiple = vals, Geërfd = onwaar)] interne afgesloten klasse NullableAttribuut : Attribuut { publieke alleen-lezen byte[] NullableFlags;
publieke NullableAttribute(byte P_0) { byte[] array = nieuwe byte[1]; array[0] = P_0; NullableFlags = array; }
publieke NullableAttribute(byte[] P_0) { NullableFlags = P_0; } }
[CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttribuutDoelen.Methode | AttribuutDoelen.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false )] interne afgesloten klasse NullableContextAttribute : Attribuut { publieke alleen-lezen byte vlag;
publieke NullableContextAttribute(byte P_0) { Vlag = P_0; } }
[CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = vals, Inherited = false)] interne verzegelde klasse RefSafetyRulesAttribuut : Attribuut { publieke alleen-lezen int Versie;
publieke RefSafetyRulesAttribute(int P_0) { Versie = P_0; } }
} Het genereert automatisch constructors en herschrijft de ToString-, GetHashCode- en Equals-methoden, en genereert automatisch enkele methoden.
p1 en p2 zijn eigenlijk twee verschillende objecten, maar omdat de compiler automatisch de comparator (IEquatable) genereerde en de Equals- en GetHashCode-methoden herschreef, was de output waar. Het aanroepen van de ToString-methode is ook zeer intuïtief om de opgenomen waarde te genereren. Zoals hieronder getoond:
record
Vereist:vereiste modifier geeft aan dat het veld of attribuut dat het toepast door alle constructors of met de objectinitialisator moet worden geïnitialiseerd. Elke expressie die wordt gebruikt om een nieuwe instantie van dat type te initialiseren, moet alle vereiste leden initialiseren. Referentie:De hyperlink-login is zichtbaar.
Init: In C# 9 en later definieert het init-sleutelwoord de accessormethode in een eigenschap of indexer. Init-only bibliotheek wijst alleen waarden toe aan attributen of indexer-elementen tijdens de objectconstructie. Dit dwingt onveranderlijkheid af, zodat zodra een object is geïnitialiseerd, het niet meer kan worden gewijzigd. Referentie:De hyperlink-login is zichtbaar.
met: Als je een instantie met enkele aanpassingen moet repliceren, kun je de with-expressie gebruiken om niet-destructieve wijzigingen te implementeren. met expressie om een nieuwe recordinstantie te creëren die een kopie is van een bestaande recordinstantie, waarbij de gespecificeerde eigenschappen en velden worden aangepast. Referentie:De hyperlink-login is zichtbaar.
Dus het record kan als volgt worden gedefinieerd:
vereist, init, en niet te zwijgen van het feit dat het eigenlijk syntaxissuiker is, zal hetRoep de automatisch gegenereerde <Clone>$-methode aanen vervolgens de waarde van het attribuut aanpassen. Als volgt:
Code:
Recordattribuut
Soms moeten we enkele functies toevoegen aan de attributen, zoals JSON-serialisatiefuncties, beschrijvingsinformatie, enzovoort.
Weg:
De hyperlink-login is zichtbaar.
De hyperlink-login is zichtbaar.
|
Vorig:ASP.NET Core (24) is gebaseerd op Refit, MemoryPack high-performance communicatieVolgend:GitHub gebruikt de REST API om de groottes van de repositorys te bekijken
|