A expressão defer atrasa a execução do código até que o escopo atual seja encerrado. Você pode usar a expressão defer para lidar com tarefas de limpeza, como restaurar variáveis. Mesmo quando houver uma saída antecipada (como return ou break) do escopo atual, as expressões em um bloco defer serão executadas desde que defer seja encontrada antes da saída.
O código a seguir mostra como usar defer para restaurar uma variável para zero enquanto ainda usa essa mesma variável como um valor de return. Nesta função, RoundScore é retornada, e as expressões no bloco defer são executadas logo depois.
Isso significa que você não precisa criar uma variável temporária para salvar o valor de RoundScore antes que ele seja zerado.
OnRoundEnd<public>() : void =
var ScoreThisRound : int = AddRoundScoreToTotalScore()
Print("Points scored this round: {ScoreThisRound}")
<# Adds RoundScore to TotalScore and resets RoundScore to 0.
Returns the RoundScore added. #>
AddRoundScoreToTotalScore<public>() : int =
defer:
set RoundScore = 0
UpdateUI()
Uso da expressão defer
Você pode usar uma expressão defer em qualquer bloco de código sequencial, como block, loop, for, if, branch ou até mesmo outro defer.
As expressões dentro de um bloco defer devem ser imediatas (e não assíncronas), com uma exceção. Expressões assíncronas ainda podem ser usadas dentro de uma defer se forem tornadas imediatas usando:
branch(sedeferestiver dentro de um bloco assíncrono, como em uma corrotina)
Uma defer não tem resultado e não pode ser usada como argumento ou valor de atribuição.
| defer | defer antes de uma saída |
|---|---|
Verse | Verse |
Clique na imagem para ampliar. | Clique na imagem para ampliar. |
Uma expressão defer apenas será executada se for encontrada antes que ocorra uma saída antecipada.
| defer com retorno antecipado | defer com uma expressão assíncrona cancelada |
|---|---|
Verse | Verse |
Clique na imagem para ampliar. | Clique na imagem para ampliar. |
Várias expressões defer que aparecerem no mesmo escopo se acumulam. A ordem em que são executadas é a ordem inversa em que são encontradas: a primeira a entrar e a última a sair. Como a última defer encontrada em um determinado escopo é executada primeiro, as expressões dentro dessa última defer encontrada podem se referir ao contexto (como variáveis) que será limpo por outras expressões defer que foram encontradas antes e executadas depois.
O código Verse não tem destruição determinística, mas defer permite um comportamento semelhante a RAII para garantir a limpeza.
| Várias expressões defer em um bloco de código | Várias expressões defer em diferentes blocos de código |
|---|---|
Verse | Verse |
Clique na imagem para ampliar. | Clique na imagem para ampliar. |
A saída antecipada é permitida dentro de um bloco defer, desde que ela não transfira o controle para fora do escopo de defer. Por exemplo, é permitido usar um loop com break dentro de uma defer, mas esse break deve manter a execução do código dentro do bloco defer. Ele não pode fazer referência a um loop fora do bloco defer.
Qualquer variável que tenha sido encontrada no escopo externo de aninhamento de uma defer pode ser usada dentro dessa expressão defer.
Lembre-se de que defer é executada por último no momento da saída do escopo. Isso significa que ela usa qualquer que seja o estado do programa (incluindo valores de variáveis) naquele momento, e não no momento em que defer é encontrada. O código abaixo imprimirá 10 porque defer é executada imediatamente após MyScore ser definido como 10.
var MyScore = 5
defer:
Print(MyScore)
set MyScore = 10Usar uma expressão defer como a última expressão dentro de um escopo equivale a não usá-la. Por exemplo, estes dois conjuntos de expressões serão executados exatamente na mesma ordem, então defer não é necessária:
| Sem defer | Com defer |
|---|---|
Verse | Verse |