Vi este consejo en otra pregunta y me preguntaba si alguien podría explicarme cómo diablos funciona esto.
try { return x; } finally { x = null; }
Quiero decir, ¿la finally
cláusula realmente se ejecuta después de la return
declaración? ¿Qué tan inseguro es este código? ¿Puedes pensar en algún hacker adicional que se pueda hacer con este try-finally
hack?
c#
.net
exception-handling
Dmitri Nesteruk
fuente
fuente
La sentencia finalmente se ejecuta, pero el valor de retorno no se ve afectado. La orden de ejecución es:
Aquí hay un breve programa para demostrar:
Esto imprime "probar" (porque eso es lo que se devuelve) y luego "finalmente" porque ese es el nuevo valor de x.
Por supuesto, si devolvemos una referencia a un objeto mutable (por ejemplo, un StringBuilder), cualquier cambio realizado en el objeto en el bloque finalmente será visible al regresar; esto no ha afectado el valor de retorno en sí (que es solo un referencia).
fuente
return
declaración, y ese valor será devuelto. La expresión no se evalúa ya que el control abandona el método.La cláusula finalmente se ejecuta después de la declaración return pero antes de regresar de la función. Creo que tiene poco que ver con la seguridad del hilo. No es un truco: finalmente se garantiza que siempre se ejecutará sin importar lo que hagas en tu bloque de prueba o tu bloque de captura.
fuente
Además de las respuestas dadas por Marc Gravell y Jon Skeet, es importante tener en cuenta que los objetos y otros tipos de referencia se comportan de manera similar cuando se devuelven, pero tienen algunas diferencias.
El "Qué" que se devuelve sigue la misma lógica que los tipos simples:
La referencia que se devuelve ya se ha evaluado antes de que a la variable local se le asigne una nueva referencia en el bloque finalmente.
La ejecución es esencialmente:
La diferencia es que aún sería posible modificar los tipos mutables utilizando las propiedades / métodos del objeto, lo que puede generar comportamientos inesperados si no se tiene cuidado.
Una segunda cosa a considerar acerca de try-return-finally es que los parámetros pasados "por referencia" aún pueden modificarse después del retorno. Solo se ha evaluado el valor de retorno y se almacena en una variable temporal en espera de ser devuelta, cualquier otra variable aún se modifica de la manera normal. El contrato de un parámetro de salida incluso puede quedar sin cumplir hasta que finalmente se bloquee de esta manera.
Como cualquier otra construcción de flujo, "try-return-finally" tiene su lugar y puede permitir un código de aspecto más limpio que escribir la estructura con la que realmente se compila. Pero debe usarse con cuidado para evitar los gotcha's.
fuente
Si
x
es una variable local, no veo el punto, yax
que de todos modos se establecerá efectivamente en nulo cuando se salga del método y el valor del valor de retorno no sea nulo (ya que se colocó en el registro antes de la llamada para establecerx
a nulo).Solo puedo ver que esto suceda si desea garantizar el cambio del valor de un campo al regresar (y después de que se determine el valor de retorno).
fuente