L'espressione defer ritarda l'esecuzione del codice fino all'uscita dell'ambito corrente. Puoi usare l'espressione defer per gestire compiti di pulizia come il ripristino di variabili. Anche quando c'è un'uscita anticipata (come return o break) dall'ambito corrente, le espressioni in un blocco defer verranno eseguite finché defer viene incontrato prima dell'uscita.
Il codice seguente mostra come utilizzare defer per azzerare una variabile, pur continuando a utilizzare la stessa variabile come valore di return. In questa funzione, RoundScore viene restituito e le espressioni del blocco defer vengono eseguite subito dopo.
Ciò significa che non è necessario creare una variabile temporanea per salvare il valore di RoundScore prima che venga azzerato.
OnRoundEnd<public>() : void =
var ScoreThisRound : int = AddRoundScoreToTotalScore()
Print("Punti segnati in questo round: {ScoreThisRound}")
<# Aggiunge RoundScore a TotalScore e azzera RoundScore.
Restituisce il RoundScore aggiunto. #>
AddRoundScoreToTotalScore<public>() : int =
defer:
imposta RoundScore = 0
UpdateUI()
imposta TotalScore += RoundScore
restituisci RoundScore
Utilizzo dell'espressione defer
Puoi usare un'espressione defer all'interno di qualsiasi blocco di codice sequenziale, come un blocco, loop, for, if, branch, o anche un altro defer.
Le espressioni all'interno di un blocco defer devono essere immediate (e non asincrone), con un'eccezione. Le espressioni asincrone possono ancora essere usate all'interno di un defer se sono rese immediate usando:
- generazione
branch(se ildeferè all'interno di un blocco asincrono come una coroutine)
Un defer non ha un risultato e non può essere usato come argomento o come valore di assegnazione.
defer | defer prima di un'uscita |
|
|
Fai clic sull'immagine per ingrandirla. |
Fai clic sull'immagine per ingrandirla. |
Un'espressione defer verrà eseguita solo se incontrata prima che si verifichi un'uscita anticipata.
defer con ritorno anticipato | defer con un'espressione asincrona annullata |
|
|
Fai clic sull'immagine per ingrandirla. |
Fai clic sull'immagine per ingrandirla. |
Più espressioni defer che appaiono nello stesso ambito si accumulano. L'ordine in cui vengono eseguite è inverso a quello in cui vengono incontrate: l'ordine first-in-last-out (FILO). Poiché l'ultimo defer incontrato in un dato ambito viene eseguito per primo, le espressioni all'interno di quell'ultimo defer possono fare riferimento a contesti (come le variabili) che saranno ripuliti da altre espressioni defer incontrate in precedenza ed eseguite successivamente.
Verse non ha distruzione deterministica, ma defer permette un comportamento simile a RAII per garantire la pulizia.
| Espressioni defer multiple in un blocco di codice | Espressioni defer multiple in diversi blocchi di codice |
|---|---|
|
|
Fai clic sull'immagine per ingrandirla. |
Fai clic sull'immagine per ingrandirla. |
L'uscita anticipata è consentita all'interno di un blocco defer, purché l'uscita non trasferisca il controllo al di fuori dell'ambito del defer. Ad esempio, l'uso di un loop con break è consentito all'interno di un defer, ma tale break deve mantenere l'esecuzione del codice all'interno del blocco defer. Non può fare riferimento a un loop al di fuori del blocco defer.
Qualsiasi variabile incontrata nell'ambito annidato esterno di un defer può essere utilizzata all'interno dell'espressione defer.
Ricorda che defer viene eseguito per ultimo al momento dell'uscita dall'ambito. Ciò significa che utilizza qualsiasi stato del programma (compresi i valori delle variabili) in quel momento, non nel momento in cui viene incontrato il defer. Il codice seguente stamperà 10 perché defer viene eseguito subito dopo che MyScore è stato impostato a 10.
var MyScore = 5
defer:
Print(MyScore)
imposta MyScore = 10
Utilizza un'espressione defer come ultima espressione all'interno di un ambito equivale a non utilizzarla affatto. Ad esempio, queste due serie di espressioni verranno eseguite esattamente nello stesso ordine, quindi defer non è necessario:
| Senza defer | Con defer |
|---|---|
|
|