Questo articolo è un articolo speculare di traduzione automatica, clicca qui per saltare all'articolo originale.

Vista: 3341|Risposta: 0

[Fonte] .NET/C# nuovo tipo di record feature

[Copiato link]
Pubblicato su 02/10/2023 09:25:51 | | | |
A partire da C# 9, puoi usare il modificatore di record per definire un tipo di riferimento che fornisce funzionalità integrate per l'incapsulamento dei dati. C# 10 consente la sintassi della classe record come sinonimo per chiarire i tipi di riferimento e consente a record struct di definire tipi di valore utilizzando la stessa funzionalità.

Casi d'uso per il record in C#(Risponde ChatGPT):

Il tipo di record in C# è una nuova funzionalità introdotta nell'ultima versione. Può essere utilizzato in molti scenari, inclusi ma non limitati ai seguenti:

Oggetto Dati Immutabile: Il tipo di record è immutabile, il che significa che una volta creato, il valore della sua proprietà non può essere modificato. Questo li rende ideali per rappresentare strutture dati immutabili come oggetti di trasferimento (DTO) o impostazioni di configurazione.
Oggetti valore: Il tipo di record può essere utilizzato per rappresentare oggetti valore la cui uguaglianza è determinata in base ai valori degli attributi piuttosto che all'equivalenza di riferimento. Questo li rende ideali per confrontare e memorizzare oggetti di valore come intervalli di date, punti di coordinate e altro ancora.
Pattern matching: Il tipo di record può essere utilizzato insieme al pattern matching, il che lo rende più comodo quando si lavora con strutture dati complesse. Puoi usare il pattern matching per controllare ed estrarre i valori degli attributi dell'oggetto record in modo da poter eseguire l'azione appropriata.
Collezioni Immutabili: Il tipo di record può essere utilizzato con tipi di collezione immutabili come ImmutableList, ImmutableDictionary, ecc., per creare oggetti di raccolta immutabili. Questo garantisce che il contenuto della raccolta non venga modificato, migliorando così l'affidabilità e la sicurezza del codice.
Questi sono solo alcuni dei casi d'uso per il tipo di record, e puoi decidere se utilizzare il tipo di record in base alle tue esigenze specifiche e alla struttura del codice.
Differenza tra record e classe e struct

La sintassi utilizzata per dichiarare e istanziare una classe o una struttura è la stessa di quella durante la registrazione di un'operazione. Basta sostituire la parola chiave class con record, oppure usare record struct invece di struct. Analogamente, la classe record supporta la stessa sintassi per le relazioni di successione. La differenza tra un record e una classe è la seguente:

  • Puoi usare parametri posizionali nel costruttore principale per creare e istanziare tipi con proprietà immutabili.
  • Metodi e operatori che indicano uguaglianza o non uguaglianza di riferimento nelle classi (ad esempio, Object.Equals(Object) e ==) indicano uguaglianza o non uguaglianza di valore nel record.
  • Puoi usare l'espressione with per creare una copia di un oggetto immutabile con un nuovo valore nell'attributo selezionato.
  • Il metodo ToString del record crea una stringa di formato che mostra il nome del tipo dell'oggetto e i nomi e i valori di tutte le sue proprietà comuni.
  • Un record può essere ereditato da un altro registro. Ma i registri non possono essere ereditati dalle classi, né le classi possono essere ereditate dai documenti.
  • La differenza tra la struttura del record e quella è che il compilatore sintetizza metodi per determinare l'uguaglianza e ToString. Il compilatore sintetizza il metodo Deconstruct per la struttura del record di posizione.


Il compilatore sintetizza una proprietà comune di solo inizializzazione per ogni parametro principale del costruttore nella classe di record. In una registrazione di registri, il compilatore sintetizza proprietà pubbliche di lettura/scrittura. Il compilatore non crea proprietà per gli argomenti principali del costruttore nei tipi di classe e struct che non contengono il modificatore di record.

Registrazione

Tipo di riferimento di classe di record (predefinito: la classe può essere omessa)
Tipo di valore di struct di record

Zucchero grammaticale record

Il record è in realtà questoZucchero sintassi, e il risultato finale è il codice di classe o struct。 Prendiamo come esempio il seguente codice:

Infine, compila nel seguente codice:

usando Sistema;
usando System.Collections.Generic;
utilizzando System.Diagnostics;
usando System.Reflection;
usando System.Runtime.CompilerServices;
utilizzando System.Security;
usando System.Security.Permissions;
usando System.Text;
utilizzando Microsoft.CodeAnalysis;

[assemblaggio: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggableModes.Default | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.Debugging Modes.EnableEditAndContinua | DebuggableAttribute.DebugggingModes.DisableOptimizations)]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.0.0")]
[modulo: Codice non verificabile]
[modulo: System.Runtime.CompilerServices.RefSafetyRules(11)]

[System.Runtime.CompilerServices.NullableContext(1)]
[System.Runtime.CompilerServices.Nullable(0)]
Classe pubblica PersonaInfo : IEquatable<PersonInfo>
{
    [CompilatoreGenerato]
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    stringa privata di lettura <FirstName>k__BackingField;

    [CompilatoreGenerato]
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    stringa privata di lettura <LastName>k__BackingField;

    [CompilatoreGenerato]
    Contratto di uguaglianza di tipo virtuale protetto
    {
        [CompilatoreGenerato]
        Ottieni
        {
            return typeof(PersonInfo);
        }
    }

    Stringa pubblica Nome
    {
        [CompilatoreGenerato]
        Ottieni
        {
            ritorno <FirstName>k__BackingField;
        }
        [CompilatoreGenerato]
        Init
        {
            <FirstName>k__BackingField = valore;
        }
    }

    stringa pubblica Cognome
    {
        [CompilatoreGenerato]
        Ottieni
        {
            ritorno <LastName>k__BackingField;
        }
        [CompilatoreGenerato]
        Init
        {
            <LastName>k__BackingField = valore;
        }
    }

    pubblicoPersonInfo(stringaNomePrima, stringa Cognome)
    {
        <FirstName>k__BackingField = Nome;
        <LastName>k__BackingField = Cognome;
        base.. ctor();
    }

    [CompilatoreGenerato]
    stringa di sovrascrittura pubblica ToString()
    {
        StringBuilder stringBuilder = nuovo StringBuilder();
        stringBuilder.Appendere("PersonInfo");
        stringBuilder.Append(" { ");
        if (PrintMembers(stringBuilder))
        {
            stringBuilder.Append(' ');
        }
        stringBuilder.Append('}');
        return stringBuilder.ToString();
    }

    [CompilatoreGenerato]
    Bool virtuale protetto PrintMembers (StringBuilder builder)
    {
        RuntimeHelpers.EnsureSufficientExecutionStack();
        muratore. Appende("Nome = ");
        muratore. Appendere (oggetto)Nome);
        muratore. Appendi(", Cognome = ");
        muratore. Appendere((oggetto)Cognome);
        ritorno vero;
    }

    [System.Runtime.CompilerServices.NullableContext(2)]
    [CompilatoreGenerato]
    operatore bool statico pubblico !=(PersonInfo a sinistra, PersonaInfo a destra)
    {
        ritorno! (sinistra == destra);
    }

    [System.Runtime.CompilerServices.NullableContext(2)]
    [CompilatoreGenerato]
    operatore bool statico pubblico ==(PersonInfo a sinistra, PersonaInfo a destra)
    {
        ritorna (oggetto)sinistra == destra || ((oggetto)sinistra != nulla && sinistra. Uguali (destra));
    }

    [CompilatoreGenerato]
    override pubblico int GetHashCode()
    {
        return (EqualityComparer<Type>. Default.GetHashCode(EqualityContract) * -1521134295 + EqualityComparer<string>. Default.GetHashCode(<FirstName>k__BackingField)) * -1521134295 + <string>EqualityComparer. Default.GetHashCode(<LastName>k__BackingField);
    }

    [System.Runtime.CompilerServices.NullableContext(2)]
    [CompilatoreGenerato]
    public override bool Equals(object obj)
    {
        return Equals(obj come PersonInfo);
    }

    [System.Runtime.CompilerServices.NullableContext(2)]
    [CompilatoreGenerato]
    bool virtuale pubblico uguale (PersonInfo altro)
    {
        ritorna (oggetto)questo == altro || ((oggetto)altro != nullo && EqualityContract == altro. EqualityContract & EqualityComparer<string>. Predefinito. Uguale(<FirstName>k__BackingField, altro.<FirstName>k__BackingField) & EqualityComparer<string>. Predefinito. Uguale (<LastName>k__BackingField, altro.<LastName>k__BackingField));
    }

    [CompilatoreGenerato]
    PersonInfo pubblica e <Clone>virtuale $()
    {
        restituisci nuova PersonaInfo(questo);
    }

    [CompilatoreGenerato]
    PersonInfo protetto (PersonInfo originale)
    {
        <FirstName>k__BackingField = originale. <FirstName>k__BackingField;
        <LastName>k__BackingField = originale. <LastName>k__BackingField;
    }

    [CompilatoreGenerato]
    public void Decostruisca (fuori stringa Nome, uscita stringa Cognome)
    {
        Nome = questo. NomeNome;
        Cognome = questo. Cognome;
    }
}

Namespace Microsoft.CodeAnalysis
{
    [CompilatoreGenerato]
    [Incorporato]
    classe sigillata interna EmbeddedAttribute : Attribute
    {
    }
}

Spazio dei nomi System.Runtime.CompilerServices
{
    [CompilatoreGenerato]
    [Microsoft.CodeAnalysis.Embedded]
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributiObiettivi.RitornoValore | AttributeTargets.GenericParameter, AllowMultiple = falso, Inherited = fals)]
    classe sigillata interna NullableAttribute : Attribute
    {
        byte pubblico di lettura sola[] NullableFlags;

        pubblico NullableAttribute(byte P_0)
        {
            byte[] array = nuovo byte[1];
            Array[0] = P_0;
            NullableFlags = array;
        }

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

    [CompilatoreGenerato]
    [Microsoft.CodeAnalysis.Embedded]
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = falso, Inherited = fals)]
    classe sigillata interna NullableContextAttribute : Attribute
    {
        byte pubblico di lettura Flag;

        pubblico NullableContextAttribute(byte P_0)
        {
            Bandiera = P_0;
        }
    }

    [CompilatoreGenerato]
    [Microsoft.CodeAnalysis.Embedded]
    [AttributeUsage(AttributeTargets.Module, AllowMultiple = falso, Inherited = fals)]
    classe sigillata interna RefSafetyRulesAttributo : Attributo
    {
        versione pubbliche di lettura int;

        public RefSafetyRulesAttribute(int P_0)
        {
            Versione = P_0;
        }
    }
}
Genera automaticamente costruttori, riscrive i metodi ToString, GetHashCode, Equals e genera automaticamente alcuni metodi.


p1 e p2 sono in realtà due oggetti diversi, ma poiché il compilatore generava automaticamente il comparatore (IEquatable) e riscriveva i metodi Equals e GetHashCode, l'output era vero. Chiamare il metodo ToString è anche molto intuitivo per riprodurre il valore registrato. Come mostrato di seguito:

.NET/C# implementa il comparatore personalizzato IEqualityComparer
https://www.itsvse.com/thread-10643-1-1.html



Registrazione

Obbligatorio:required indica che il campo o l'attributo applicato deve essere inizializzato da tutti i costruttori o utilizzando l'inizializzatore di oggetti. Qualsiasi espressione usata per inizializzare una nuova istanza di quel tipo deve inizializzare tutti i membri richiesti.
Riferimento:Il login del link ipertestuale è visibile.

Init: In C# 9 e successive, la parola chiave init definisce il metodo accessor in una proprietà o in un indicizzatore. La libreria solo init assegna valori solo agli attributi o agli elementi dell'indicizzatore durante la costruzione degli oggetti. Questo impone immutabilità, quindi una volta che un oggetto è inizializzato, non può più essere modificato.
Riferimento:Il login del link ipertestuale è visibile.

con: Se devi replicare un'istanza con alcune modifiche, puoi usare l'espressione con per implementare cambiamenti non distruttivi. con expression per creare una nuova istanza di record che sia una copia di un'istanza di record esistente, modificando le proprietà e i campi specificati.
Riferimento:Il login del link ipertestuale è visibile.

Quindi il record può essere definito come segue:

richiesto, init, senza contare che, con è effettivamente zucchero sintassi, lo faràChiama il metodo $ generato automaticamente <Clone>e poi modificare il valore dell'attributo. Come segue:



Codice:



Attributo del record

A volte dobbiamo aggiungere alcune caratteristiche agli attributi, come caratteristiche di serializzazione JSON, informazioni di descrizione, ecc.



Risorse:

Il login del link ipertestuale è visibile.
Il login del link ipertestuale è visibile.





Precedente:ASP.NET Core (24) si basa su Refit e comunicazione ad alte prestazioni MemoryPack
Prossimo:GitHub utilizza l'API REST per visualizzare le dimensioni dei repository
Disconoscimento:
Tutto il software, i materiali di programmazione o gli articoli pubblicati dalla Code Farmer Network sono destinati esclusivamente all'apprendimento e alla ricerca; I contenuti sopra elencati non devono essere utilizzati per scopi commerciali o illegali, altrimenti gli utenti dovranno sostenere tutte le conseguenze. Le informazioni su questo sito provengono da Internet, e le controversie sul copyright non hanno nulla a che fare con questo sito. Devi eliminare completamente i contenuti sopra elencati dal tuo computer entro 24 ore dal download. Se ti piace il programma, ti preghiamo di supportare software autentico, acquistare la registrazione e ottenere servizi autentici migliori. In caso di violazione, vi preghiamo di contattarci via email.

Mail To:help@itsvse.com