Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Un meetup richiede etichette badge nell'ordine dei nomi. Ogni partecipante richiede una o più copie e ogni etichetta include un messaggio per il ruolo del partecipante. In questa esercitazione si combinano piccole tecniche C# per produrre le etichette senza una raccolta separata di stringhe formattate.
Questa esercitazione è destinata agli sviluppatori che conoscono metodi, cicli e raccolte C# di base. Si sceglie dove appartengono le operazioni brevi, si rendono esplicite le dipendenze helper e si decide quando il programma produce risultati. Per il ragionamento alla base di queste scelte, vedere Sviluppo del software.
Prerequisites
- .NET 10 SDK.
- Un editor di testo e un terminale.
Iniziare con un'etichetta per partecipante
Creare una cartella denominata
BadgeLabelse un file denominatoProgram.csal suo interno.Copiare il testo sorgente completo nella sezione seguente in
Program.cs. Usare lo stesso file per ogni passaggio e esperimento:#define BADGE_SORT #define BADGE_COPIES #define BADGE_FORMAT #define BADGE_COUNT // #define BADGE_DIAGNOSTICS // #define BADGE_REPEAT // #define BADGE_SNAPSHOT Attendee[] attendees = [ new("Ben", "Host", 1), new("Ada", "Guest", 2) ]; #if BADGE_SORT #if BADGE_DIAGNOSTICS Console.WriteLine("Before query definition."); #endif var orderedAttendees = attendees.OrderBy( #if BADGE_DIAGNOSTICS attendee => { Console.WriteLine($"Sort key: {attendee.Name}"); return attendee.Name; }, StringComparer.Ordinal); #else attendee => attendee.Name, StringComparer.Ordinal); #endif #if BADGE_DIAGNOSTICS Console.WriteLine("After query definition."); #endif #else var orderedAttendees = attendees; #endif #if BADGE_SNAPSHOT var attendeesToPrint = orderedAttendees.ToList(); #else var attendeesToPrint = orderedAttendees; #endif int passes = 1; #if BADGE_REPEAT passes = 2; #endif for (int pass = 0; pass < passes; pass++) { #if BADGE_COUNT int expected = attendees.Sum(attendee => attendee.Copies); int printed = 0; #endif foreach (Attendee attendee in attendeesToPrint) { #if BADGE_COPIES var labels = CreateLabels(attendee); #if BADGE_DIAGNOSTICS Console.WriteLine($"Sequence created: {attendee.Name}"); #endif foreach (string label in labels) { Console.WriteLine(label); #if BADGE_COUNT printed++; #endif } #else Console.WriteLine($"{attendee.Name} | {attendee.Role}"); #endif } #if BADGE_COUNT if (printed != expected) { throw new InvalidOperationException("Label count doesn't match the request."); } Console.WriteLine($"Printed {printed} of {expected} requested labels."); #endif } #if BADGE_COPIES static IEnumerable<string> CreateLabels(Attendee attendee) { #if BADGE_DIAGNOSTICS Console.WriteLine($"Iterator started: {attendee.Name}"); #endif ArgumentOutOfRangeException.ThrowIfNegativeOrZero(attendee.Copies); #if BADGE_FORMAT string message = attendee.Role switch { "Guest" => "Welcome!", "Host" => "Ask me for help", _ => throw new ArgumentException( $"Unsupported role: {attendee.Role}.", nameof(attendee)) }; #endif for (int copy = 1; copy <= attendee.Copies; copy++) { #if BADGE_FORMAT yield return FormatLabel( attendee.Name, attendee.Role, message, copy, attendee.Copies); #else yield return $"{attendee.Name} | {attendee.Role} [{copy}/{attendee.Copies}]"; #endif } #if BADGE_FORMAT static string FormatLabel( string name, string role, string message, int copy, int total) => $"{name} | {role} | {message} [{copy}/{total}]"; #endif } #endif record Attendee(string Name, string Role, int Copies);Nella parte superiore del file impostare come commento le quattro righe attive
#define. Lasciare anche le tre righe dell'esperimento impostate come commento.Da tale cartella eseguire l'app basata su file:
dotnet run --file Program.cs
Il programma scrive:
Ben | Host
Ada | Guest
Il file contiene ogni fase. Da ora in poi, modificare solo le #define righe nella parte superiore, non i corpi o le dichiarazioni dei metodi. Una #if direttiva include codice solo quando viene definito il relativo simbolo; un ramo #else fornisce l'alternativa. Vedi Compilazione condizionale.
Rimuovere il commento da una riga di fase aggiuntiva in ogni passaggio e mantenere attivate le linee di fase precedenti:
| Stage | Simboli della fase attiva |
|---|---|
| Un'etichetta per ogni partecipante | None |
| Ordina i partecipanti | BADGE_SORT |
| Crea copie |
BADGE_SORT, BADGE_COPIES |
| Formattare i messaggi |
BADGE_SORT, BADGE_COPIES, BADGE_FORMAT |
| Verifica il conteggio |
BADGE_SORT, BADGE_COPIES, BADGE_FORMATBADGE_COUNT |
Il codice sorgente scaricato abilita tutti e quattro i simboli di fase, quindi esegue il programma finale per impostazione predefinita. Gli altri tre simboli controllano esperimenti facoltativi e rimangono disattivati durante la progressione normale. Questi simboli usano un prefisso BADGE_ per evitare simboli definiti dall’SDK come TRACE.
Gli estratti seguenti evidenziano il codice già presente nel file. Non copiarli sull'intero programma.
Attendee[] attendees =
[
new("Ben", "Host", 1),
new("Ada", "Guest", 2)
];
La Attendee dichiarazione definisce un record, un tipo che raggruppa i dati correlati e fornisce l'uguaglianza basata su valori. Ogni partecipante ha un Name, un Role e un numero richiesto di Copies. Un record si adatta a questo piccolo modello di dati perché il programma trasferisce i dati dei partecipanti tra operazioni senza modificarli. Per altre informazioni su questo tipo, vedere Record.
L'input fisso usa un array e un'espressione collection. In ogni new(...) chiamata, C# deduce Attendee dal tipo di elemento della matrice. Vedere Target-typed new.
Le istruzioni di primo livello consentono di eseguire l'esempio senza scrivere un Main metodo.
Il foreach loop legge ogni partecipante e una stringa interpolata inserisce i relativi valori nell'output. Il ciclo attualmente ignora Copies.
Mantenere questo piccolo input durante lo sviluppo del programma: Ben richiede una copia e Ada richiede due. Solo Guest e Host sono ruoli supportati e i conteggi delle copie devono essere positivi.
Ordinare con un'espressione lambda
Per ordinare i partecipanti per nome, rimuovere il commento #define BADGE_SORT. Lasciare gli altri simboli commentati. Il ramo di ordinamento definisce questa query:
var orderedAttendees = attendees.OrderBy(
#if BADGE_DIAGNOSTICS
attendee =>
{
Console.WriteLine($"Sort key: {attendee.Name}");
return attendee.Name;
}, StringComparer.Ordinal);
#else
attendee => attendee.Name, StringComparer.Ordinal);
#endif
Con la diagnostica disattivata, il #else ramo fornisce l'espressione lambda breve. Il ciclo stampa i partecipanti ordinati:
foreach (Attendee attendee in attendeesToPrint)
{
#if BADGE_COPIES
var labels = CreateLabels(attendee);
#if BADGE_DIAGNOSTICS
Console.WriteLine($"Sequence created: {attendee.Name}");
#endif
foreach (string label in labels)
{
Console.WriteLine(label);
#if BADGE_COUNT
printed++;
#endif
}
#else
Console.WriteLine($"{attendee.Name} | {attendee.Role}");
#endif
}
Eseguire lo stesso comando. L'output ora mette Ada per prima:
Ada | Guest
Ben | Host
attendee => attendee.Name è un'espressione lambda, una funzione senza nome fornita dove il codice richiede un comportamento. In questo caso, l'espressione lambda seleziona il nome in base al quale eseguire l'ordinamento. L'espressione lambda rimane inline, direttamente nella OrderBy chiamata, perché è breve e lo scopo è chiaro. È possibile estrarre la selezione in un metodo helper denominato, ma un nome di metodo non spiega meglio questa selezione basata su una sola proprietà. Vedi Espressioni lambda.
OrderByfa parte di LINQ (Language Integrated Query), un set di funzionalità C# e API .NET per le query sui dati. Vedere le query LINQ.
In questo esempio viene utilizzata la sintassi del metodo, con cui vengono chiamati direttamente i metodi LINQ. Al contrario, la sintassi di query usa clausole C# come from, orderbye select:
var orderedAttendees =
from attendee in attendees
orderby attendee.Name
select attendee;
Il compilatore converte la sintassi di query in chiamate al metodo. La sintassi delle query può semplificare la lettura di una query con diverse clausole; la sintassi del metodo mantiene questo singolo ordinamento breve e consente di passare un comparatore a OrderBy. L'esempio di sintassi di query usa l'operatore di confronto di stringhe predefinito, quindi non garantisce lo stesso ordine tra le impostazioni cultura. Mantenere la versione con sintassi di metodo per questo programma. Vedi metodo LINQ e sintassi di query.
Per mantenere l'output indipendente dalle impostazioni cultura del computer, l'esempio usa Ordinal per i confronti dei nomi. Per i nomi brevi, l'ordine è alfabetico. Vedere Ordinare i dati con LINQ.
La var dichiarazione consente al compilatore di dedurre il tipo della variabile di query. La orderedAttendees variabile descrive una query, non una raccolta ordinata completata.
Enumerare una sequenza significa leggere i suoi elementi uno alla volta.
OrderBy legge e ordina tutti gli elementi quando foreach richiede per la prima volta un elemento.
Osservare l'ordine di esecuzione
L'esecuzione posticipata indica che il lavoro inizia quando il codice enumera una sequenza anziché quando il codice definisce la query. Vedere Eseguire una query. Usare l'output di diagnostica per visualizzare la differenza:
Mantieni abilitato solo
BADGE_SORTtra i simboli di fase.Rimuovere il commento
#define BADGE_DIAGNOSTICSnella parte superiore dello stesso file. I rami di diagnostica circondano la definizione di query con messaggi e usano un'espressione lambda che stampa ogni chiave di ordinamento:#if BADGE_SORT #if BADGE_DIAGNOSTICS Console.WriteLine("Before query definition."); #endif var orderedAttendees = attendees.OrderBy( #if BADGE_DIAGNOSTICS attendee => { Console.WriteLine($"Sort key: {attendee.Name}"); return attendee.Name; }, StringComparer.Ordinal); #else attendee => attendee.Name, StringComparer.Ordinal); #endif #if BADGE_DIAGNOSTICS Console.WriteLine("After query definition."); #endif #else var orderedAttendees = attendees; #endifEseguire
dotnet run --file Program.csdi nuovo. Prima di leggere l'output, prevedere seSort key:viene visualizzato prima o dopoAfter query definition..
L'output è il seguente:
Before query definition.
After query definition.
Sort key: Ben
Sort key: Ada
Ada | Guest
Ben | Host
Nessuna chiave di ordinamento compare tra i due messaggi di definizione di query. La lambda viene eseguita solo quando foreach richiede il primo risultato. Entrambi i messaggi chiave vengono visualizzati prima della prima etichetta perché OrderBy ha bisogno di tutte le chiavi prima di poter determinare quale partecipante viene per primo. Le chiavi seguono l'ordine di input, Ben quindi Ada; i risultati seguono l'ordine ordinato, Ada e poi Ben.
L'espressione lambda di diagnostica richiede sia un messaggio che una chiave restituita, quindi usa un corpo di istruzione a blocco con parentesi graffe e return, anziché il corpo originale con un'espressione singola.
Con la diagnostica attivata, provare le due opzioni dell'esperimento nello stesso file. Non sono necessarie modifiche ai cicli o alle query:
Rimuovere il commento
#define BADGE_REPEATed eseguire di nuovo:Before query definition. After query definition. Sort key: Ben Sort key: Ada Ada | Guest Ben | Host Sort key: Ben Sort key: Ada Ada | Guest Ben | HostIl secondo passaggio ripete l'ordinamento. La variabile di query non memorizza nella cache i risultati.
Mantenere
BADGE_REPEATabilitato, decommentare#define BADGE_SNAPSHOTed eseguire di nuovo:Before query definition. After query definition. Sort key: Ben Sort key: Ada Ada | Guest Ben | Host Ada | Guest Ben | HostI due messaggi chiave vengono ora visualizzati una sola volta, durante
ToList, prima che uno dei due pass stampi le etichette. Entrambi i pass leggono i partecipanti archiviati.
Queste opzioni selezionano la sequenza da enumerare e il numero di passate:
#if BADGE_SNAPSHOT
var attendeesToPrint = orderedAttendees.ToList();
#else
var attendeesToPrint = orderedAttendees;
#endif
int passes = 1;
#if BADGE_REPEAT
passes = 2;
#endif
L'esecuzione eager indica che un'operazione viene eseguita immediatamente anziché attendere l'enumerazione successiva.
ToList esegue la query immediatamente e ne archivia i risultati in un elenco. Entrambi i passaggi ora leggono i partecipanti archiviati senza eseguire di nuovo l'ordinamento. Al contrario, la definizione della OrderBy query rinvia ancora l'ordinamento: legge e memorizza nel buffer tutti gli input solo all'inizio dell'enumerazione. Il buffering non significa che la query venga eseguita quando viene definita. Usare uno snapshot quando è necessario riutilizzare i risultati senza ricalcolare i risultati; mantenere la query posticipata quando si desidera che ogni enumerazione legga l'input corrente. Vedere Comporre query con risultati memorizzati nella cache.
Prima di continuare, commenta di nuovo BADGE_DIAGNOSTICS, BADGE_REPEAT e BADGE_SNAPSHOT. Mantieni BADGE_SORT abilitato. Eseguire l'app per verificare che vengano visualizzate solo le due etichette ordinate.
Produrre le copie richieste con un fascicolatore
Per espandere ogni partecipante nel numero di etichette richiesto, rimuovere il commento #define BADGE_COPIES insieme a BADGE_SORT. Il ciclo seleziona ora il BADGE_COPIES ramo illustrato in precedenza e chiama l'iteratore già nel file:
#if BADGE_COPIES
static IEnumerable<string> CreateLabels(Attendee attendee)
{
#if BADGE_DIAGNOSTICS
Console.WriteLine($"Iterator started: {attendee.Name}");
#endif
ArgumentOutOfRangeException.ThrowIfNegativeOrZero(attendee.Copies);
#if BADGE_FORMAT
string message = attendee.Role switch
{
"Guest" => "Welcome!",
"Host" => "Ask me for help",
_ => throw new ArgumentException(
$"Unsupported role: {attendee.Role}.", nameof(attendee))
};
#endif
for (int copy = 1; copy <= attendee.Copies; copy++)
{
#if BADGE_FORMAT
yield return FormatLabel(
attendee.Name, attendee.Role, message, copy, attendee.Copies);
#else
yield return $"{attendee.Name} | {attendee.Role} [{copy}/{attendee.Copies}]";
#endif
}
#if BADGE_FORMAT
static string FormatLabel(
string name, string role, string message, int copy, int total) =>
$"{name} | {role} | {message} [{copy}/{total}]";
#endif
}
#endif
Eseguire di nuovo l'app:
Ada | Guest [1/2]
Ada | Guest [2/2]
Ben | Host [1/1]
CreateLabels è un iteratore, una funzione che produce elementi di sequenza uno alla volta. Il IEnumerable<T> tipo restituito, scritto come IEnumerable<string>, rappresenta una sequenza di stringhe. Ognuno yield return fornisce un'etichetta al ciclo interno foreach, che la stampa prima di richiedere l'etichetta successiva. Vedi Iteratori.
Il for ciclo conta le copie da 1 a attendee.Copies. Un partecipante produce tante stringhe quante richieste Copies. Una raccolta funziona anche, ma il chiamante necessita solo di ogni etichetta una sola volta. L'iteratore evita una raccolta di etichette separata e mantiene il ciclo copy-number insieme. I cicli esterni e interni foreach separano l'ordine degli iscritti dalla produzione di etichette. Il chiamante rimane responsabile della stampa.
Chiamare CreateLabels(attendee) non esegue il corpo. Analogamente alla query LINQ, l'iteratore usa l'esecuzione posticipata. Il comando interno foreach avvia il lavoro, incluso il controllo della copia positiva. Una nuova enumerazione itera nuovamente l'iteratore. A differenza di OrderBy, che legge e ordina tutti i partecipanti prima del primo risultato, questo iteratore fornisce un'etichetta senza creare le etichette rimanenti.
Per osservare l'ordine di esecuzione dell'iteratore, rimuovere nuovamente il commento #define BADGE_DIAGNOSTICS . Mantieni BADGE_REPEAT e BADGE_SNAPSHOT disattivati. La diagnostica mostra ora sia l'ordinamento che l'iteratore:
Before query definition.
After query definition.
Sort key: Ben
Sort key: Ada
Sequence created: Ada
Iterator started: Ada
Ada | Guest [1/2]
Ada | Guest [2/2]
Sequence created: Ben
Iterator started: Ben
Ben | Host [1/1]
Per ogni partecipante, il messaggio creato dalla sequenza viene visualizzato prima del messaggio avviato dall'iteratore e delle etichette. La creazione della sequenza non immette nel corpo dell'iteratore; la richiesta del primo elemento lo fa. Commenta di nuovo BADGE_DIAGNOSTICS prima di continuare.
Gli stessi controlli dell'esperimento rimangono disponibili nelle fasi successive.
BADGE_REPEAT enumera i partecipanti due volte e crea di nuovo la sequenza di etichette di ogni partecipante.
BADGE_SNAPSHOT memorizza nella cache solo i partecipanti ordinati, non le stringhe di etichetta, quindi impedisce un altro ordinamento, ma non impedisce l'esecuzione dell'iteratore a ogni iterazione.
Il ThrowIfNegativeOrZero controllo segnala l'input non valido anziché non produrre etichette in modo silenzioso. Un'eccezione segnala un errore che interrompe la normale esecuzione; vedere Creare e generare eccezioni. In questo caso, un conteggio di copie non valido arresta il programma invece di ignorare automaticamente il partecipante.
Calcolare un messaggio e assegnare un nome al passaggio di formattazione
Ogni ruolo richiede un messaggio diverso. Rimuovere il commento #define BADGE_FORMAT, e lasciare BADGE_COPIES e BADGE_SORT abilitati. Lo stesso iteratore include ora il calcolo del messaggio:
#if BADGE_FORMAT
string message = attendee.Role switch
{
"Guest" => "Welcome!",
"Host" => "Ask me for help",
_ => throw new ArgumentException(
$"Unsupported role: {attendee.Role}.", nameof(attendee))
};
#endif
Seleziona anche il yield return FormatLabel(...) ramo e include questo helper locale:
#if BADGE_FORMAT
static string FormatLabel(
string name, string role, string message, int copy, int total) =>
$"{name} | {role} | {message} [{copy}/{total}]";
#endif
Eseguire di nuovo l'app:
Ada | Guest | Welcome! [1/2]
Ada | Guest | Welcome! [2/2]
Ben | Host | Ask me for help [1/1]
L'espressioneswitch calcola il messaggio una volta per partecipante, prima del ciclo di copia. Un'espressione si adatta perché ogni ruolo seleziona un valore da assegnare a message. Una if/else catena o un'istruzione switch funzionerebbe, ma ripeterebbe l'assegnazione in ogni ramo.
Corrispondenza di pattern testa un'espressione rispetto a un pattern specificato. Qui, attendee.Role è l'espressione di input e i modelli costanti"Guest" e "Host" ne testano il valore valutato per selezionare il messaggio corrispondente. Il pattern discard _ corrisponde a qualsiasi altro ruolo e genera un'eccezione, quindi i ruoli non supportati non ricevono un messaggio predefinito fuorviante. Vedi corrispondenza dei modelli.
L'operatorenameof fornisce all'eccezione il nome del parametro attendee. A differenza di una stringa hardcoded, tale nome rimane corretto se si rinomina il parametro con uno strumento di refactoring.
FormatLabel è una funzione locale, una funzione denominata dichiarata all'interno di un'altra funzione. Poiché solo CreateLabels necessita dell'operazione di formattazione, la sua collocazione all'interno di CreateLabels limita l'helper all'operazione che lo usa. Un metodo membro privato in una classe renderebbe disponibile l'helper ad altri membri di tale classe. Scegliere l'ambito più ampio se più operazioni richiedono la stessa operazione di formattazione. Vedi Funzioni locali.
Il nome FormatLabel consente di seguire il ciclo di copia senza leggere i dettagli di formattazione. Anche mantenere la stringa interpolata in yield return funzionerebbe, come nel passaggio precedente. Il nome diventa più utile ora che un'etichetta include un messaggio specifico del ruolo. Il corpo dell'espressione dell'helper => restituisce la stringa formattata.
Tutti gli input di formattazione arrivano tramite parametri. Una funzione locale non statica può acquisire o usare variabili dall'ambito circostante. Il static modificatore impedisce l'acquisizione, quindi le relative dipendenze rimangono esplicite. Vedere Parametri e stato acquisito.
Poiché CreateLabels è ancora un iteratore, il controllo del ruolo viene eseguito solo all'avvio dell'enumerazione. Per questo input controllato, questi controlli appartengono alla produzione delle etichette. Il programma non promette di convalidare tutti i partecipanti prima di stampare qualsiasi etichetta.
Verificare il totale ed eseguire il programma completo
Per confrontare l'effettiva produzione di etichette con il conteggio richiesto, rimuovere il commento #define BADGE_COUNT. Tutti e quattro i simboli di fase sono ora abilitati. Lasciare i tre simboli dell'esperimento commentati per l'output finale normale.
La configurazione del conteggio viene eseguita prima del ciclo dei partecipanti:
#if BADGE_COUNT
int expected = attendees.Sum(attendee => attendee.Copies);
int printed = 0;
#endif
Sum usa l'esecuzione eager per aggiungere i conteggi di copia dalla matrice di input. A differenza di OrderBy, restituisce un numero, non una sequenza da enumerare in un secondo momento. L'espressione lambda, attendee => attendee.Copies, seleziona il conteggio delle copie inline. Come per la selezione del nome, un metodo helper separato non chiarirebbe questa breve espressione. Un ciclo con un accumulatore funzionerebbe anche; Sum indica direttamente che si desidera un totale. Vedere Metodi LINQ comuni.
L'printed++incremento nel loop con etichetta aumenta il contatore solo quando il loop riceve un'etichetta. Dopo questo ciclo, l'istruzioneif confronta il conteggio con il totale richiesto e genera un'eccezione se differiscono:
#if BADGE_COUNT
if (printed != expected)
{
throw new InvalidOperationException("Label count doesn't match the request.");
}
Console.WriteLine($"Printed {printed} of {expected} requested labels.");
#endif
Hai raggiunto la configurazione predefinita del programma completo copiato all'inizio. Nessun metodo o dichiarazione da modificare:
#define BADGE_SORT
#define BADGE_COPIES
#define BADGE_FORMAT
#define BADGE_COUNT
// #define BADGE_DIAGNOSTICS
// #define BADGE_REPEAT
// #define BADGE_SNAPSHOT
Eseguilo con dotnet run --file Program.cs. L'output è il seguente:
Ada | Guest | Welcome! [1/2]
Ada | Guest | Welcome! [2/2]
Ben | Host | Ask me for help [1/1]
Printed 3 of 3 requested labels.
L’array di input è già in memoria.
Sum lo legge immediatamente, OrderBy lo ordina quando inizia il ciclo dei partecipanti e CreateLabels produce stringhe man mano che il ciclo interno avanza. Il programma non crea mai una raccolta separata di etichette. Per indicazioni più generali sulle query, vedere LINQ e raccolte.
Per rivedere la diagnostica con il programma finale, abilitare BADGE_DIAGNOSTICS da solo tra i simboli dell'esperimento. L'output è il seguente:
Before query definition.
After query definition.
Sort key: Ben
Sort key: Ada
Sequence created: Ada
Iterator started: Ada
Ada | Guest | Welcome! [1/2]
Ada | Guest | Welcome! [2/2]
Sequence created: Ben
Iterator started: Ben
Ben | Host | Ask me for help [1/1]
Printed 3 of 3 requested labels.
Se si abilita BADGE_REPEATanche , ogni passaggio verifica e segnala il proprio conteggio. Con BADGE_SNAPSHOT abilitato, le chiavi di ordinamento vengono visualizzate una sola volta, ma i messaggi dell'iteratore, le etichette e il report del conteggio vengono comunque visualizzati a ogni passaggio. Mettere in commento i simboli dell'esperimento per ripristinare l'output finale normale.
Summary
Ogni tecnica serve una parte diversa della stessa attività:
- Le espressioni lambda e LINQ selezionano i nomi e i conteggi delle copie inline per l'ordinamento e il totale.
- Un iteratore esprime la produzione uno-a-molti personalizzata e lascia il consumo di etichette al chiamante.
-
Un'
switchespressione calcola un valore specifico del ruolo e rende espliciti i ruoli non supportati. - Una funzione locale assegna un nome al passaggio di formattazione, limita l'ambito e ne indica gli input.
Scegliere questi formulari quando l'ambito, le dipendenze e l'ordine di esecuzione corrispondono all'operazione. Un ciclo diretto, un metodo condiviso o una raccolta completata possono adattarsi meglio ad altri chiamanti.