La expresión defer retrasa la ejecución del código hasta que se salga del ámbito actual. Puedes utilizar la expresión defer para realizar tareas de limpieza, como restablecer variables. Incluso si se produce una salida anticipada (such as return or break) del ámbito actual, las expresiones de un bloque defer se ejecutarán siempre que defer aparezca antes de la salida.
El siguiente código muestra cómo usar defer para restablecer una variable a cero mientras se sigue usando esa misma variable como valor de retorno. En esta función, se devuelve RoundScore, y las expresiones del bloque defer se ejecutan inmediatamente después.
Esto significa que no es necesario crear una variable temporal para guardar el valor de RoundScore antes de que se restablezca en cero.
OnRoundEnd<public>() : void =
var ScoreThisRound : int = AddRoundScoreToTotalScore()
Print("Points scored this round: {ScoreThisRound}")
<# Añade RoundScore a TotalScore y restablece RoundScore a 0.
Devuelve el RoundScore añadido. #>
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 en cualquier bloque de código secuencial como bloque, bucle, for, if, rama, o incluso otro defer.
Las expresiones dentro de un bloque defer deben ser inmediatas (y no asíncronas), con una excepción. Las expresiones asíncronas se pueden seguir utilizando en una defer si se hacen inmediatas con lo siguiente:
- spawn:
branch(sideferestá dentro de un bloque asíncrono como en una corrutina).
Una expresión defer no tiene resultado y no puede utilizarse como un argumento o un 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 aparece antes de que se produzca una salida anticipada.
| defer con un retorno anticipado | defer con una expresión asíncrona cancelada |
|---|---|
|
|
Haz clic en la imagen para ampliarla. |
Haz clic en la imagen para ampliarla. |
Múltiples expresiones defer que aparecen en el mismo ámbito se acumulan. El orden en el que se ejecutan es el orden inverso en la que se encuentran, orden FILO (siglas en inglés de primero en entrar último en salir). Como la última expresión defer que aparece en un ámbito dado se ejecuta primero, las expresiones dentro de esa última defer pueden referirse a contextos (como variables) que limpiarán otras expresiones defer que aparecieron antes y se ejecutaron después.
Verse no dispone de una 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 de defer. Por ejemplo, se puede utilizar un bucle con break dentro de una expresión defer, pero ese break debe mantener la ejecución del código dentro del bloque defer. No puede referirse a un loop fuera del bloque defer.
Todas las variables que hayan aparecido en el ámbito externo anidado de una expresión defer pueden utilizarse dentro de dicha expresión.
Recuerda que defer se ejecuta en último lugar al salir del ámbito. Esto significa que utiliza el estado del programa (incluidos los valores de las variables) en ese momento, no en el momento en que aparece defer. El siguiente código 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. Por ejemplo, estos dos conjuntos de expresiones se ejecutarán exactamente en el mismo orden, por lo que defer no es necesaria:
| Sin defer | Con defer |
|---|---|
|
|