La expresión defer retrasa la ejecución del código hasta que se sale del ámbito actual. Puedes utilizar la expresión defer para realizar tareas de limpieza como restablecer variables. Incluso cuando hay una salida anticipada (por ejemplo, return o break) del ámbito actual, las expresiones de un bloque defer se ejecutarán siempre que defer se encuentre antes de la salida.
El siguiente código muestra cómo utilizar defer para poner a cero una variable sin dejar de utilizar esa misma variable como valor devuelto. En esta función, se devuelve RoundScore y las expresiones del bloque defer se ejecutan inmediatamente después.
Esto significa que no necesitas crear una variable temporal para guardar el valor de RoundScore antes de que se ponga a cero.
OnRoundEnd<public>() : void =
var ScoreThisRound : int = AddRoundScoreToTotalScore()
Print("Puntos conseguidos en esta ronda: {ScoreThisRound}")
<# Añade RoundScore a TotalScore y restablece RoundScore a 0.
Devuelve la RoundScore añadida. #>
AddRoundScoreToTotalScore<public>() : int =
defer:
set RoundScore = 0
UpdateUI()
set TotalScore += RoundScore
return RoundScore
Uso de la expresión defer
Puedes utilizar una expresión defer dentro de cualquier [bloque de código] (verse-glossary#code-block) secuencial, como block, loop, for, if, branch o incluso otro defer.
Las expresiones dentro de un bloque defer deben ser inmediatas (y no async). Pero hay una excepción. Las expresiones asíncronas pueden seguir utilizándose dentro de un defer si se hacen inmediatas utilizando:
- spawn
branch(si eldeferestá dentro de un bloque asíncrono, como en una corrutina).
Un defer no tiene resultado, y no puede utilizarse como argumento ni como valor de asignación.
| defer | defer antes de una salida |
|---|---|
|
|
Haz clic en la imagen para ampliarla. |
Haz clic en la imagen para ampliarla. |
Una expresión defer solo se ejecutará si se encuentra antes de que se produzca una salida anticipada.
| defer con retorno anticipado | defer con una expresión asíncrona cancelada |
|---|---|
|
|
Haz clic en la imagen para ampliarla. |
Haz clic en la imagen para ampliarla. |
Se acumulan varias expresiones defer que aparecen en el mismo ámbito. El orden en que se ejecutan es el orden inverso en que se encuentran: orden de entrada y salida (FILO). Dado que el último defer encontrado en un ámbito determinado se ejecuta primero, las expresiones dentro de ese último defer encontrado pueden referirse a contextos (como variables) que serán limpiados por otras expresiones defer encontradas antes y ejecutadas después.
Verse no tiene destrucción determinista, pero defer permite un comportamiento similar a RAII para garantizar la limpieza.
Múltiples expresiones defer en un bloque de código |
Múltiples expresiones defer en diferentes bloques de código |
|---|---|
|
|
Haz clic en la imagen para ampliarla. |
Haz clic en la imagen para ampliarla. |
Se permite la salida anticipada dentro de un bloque defer siempre que la salida no transfiera el control fuera del ámbito del defer. Por ejemplo, está permitido utilizar un bucle con break dentro de un defer, pero ese break debe mantener la ejecución del código dentro del bloque defer. No puede hacer referencia a un loop fuera del bloque defer.
Cualquier variable que se haya encontrado en el ámbito de anidamiento exterior de un defer puede utilizarse dentro de esa expresión defer.
Recuerda que defer se ejecuta en último lugar al salir del ámbito. Esto significa que utiliza cualquiera que sea el estado del programa (incluidos los valores de las variables) en ese momento, no en el momento en que se encuentra el defer. El código siguiente imprimirá 10 porque defer se ejecuta inmediatamente después de que MyScore se establezca en 10.
var MyScore = 5
defer:
Print(MyScore)
set MyScore = 10
Utilizar una expresión defer como última expresión dentro de un ámbito es lo mismo que no utilizarla en absoluto. Por ejemplo, estos dos conjuntos de expresiones se ejecutarán exactamente en el mismo orden, por lo que defer no es necesario:
| Sin defer | Con defer |
|---|---|
|
|