No, no hay manera de hacer esto directamente. Hay algunas diferentes escuelas de pensamiento sobre cómo hacer este tipo de cosas. Comparar y contrastar estos dos:
originalState = GetState();
SetState(newState);
DoSomething();
SetState(originalState);
vs
originalState = GetState();
SetState(newState);
try
{
DoSomething();
}
finally
{
SetState(originalState);
}
Mucha gente le dirá que el último es "más seguro".
No es necesariamente así.
La diferencia entre los dos es, por supuesto, que este último restablece el estado incluso si DoSomething() arroja una excepción. ¿Es mejor que mantener el estado mutado en un escenario de excepción? ¿Qué lo hace mejor? Tiene una excepción inesperada no controlada que informa que algo horrible y inesperado ha sucedido.Su estado interno podría ser completamente inconsistente y arbitrariamente desordenado; nadie sabe lo que podría estar sucediendo en el momento de la excepción. Todo lo que sabemos es que DoSomething probablemente estaba tratando de hacer algo para el estado mutado.
¿Es realmente lo correcto en el escenario donde algo terrible y desconocido ha sucedido para seguir revolviendo esa olla en particular y tratando de mutar el estado que acaba de causar una excepción otra vez?
A veces eso va a ser lo correcto y, a veces, empeorará las cosas. El escenario en el que estás realmente depende de lo que esté haciendo exactamente el código, así que piensa cuidadosamente qué es lo correcto antes de elegir ciegamente uno u otro.
Francamente, prefiero resolver el problema al no entrar en la situación en primer lugar. Nuestro diseño de compilador existente utiliza este patrón de diseño, y francamente, es muy irritante. En el compilador de C# existente, el mecanismo de informe de errores es "de efecto secundario". Es decir, cuando una parte del compilador recibe un error, llama al mecanismo de informe de errores que luego muestra el error al usuario.
Este es un problema importante para la unión de lambda. Si usted tiene:
void M(Func<int, int> f) {}
void M(Func<string, int> f) {}
...
M(x=>x.Length);
entonces la forma en que esto funciona es que tratar de unir
M((int x)=>{return x.Length;});
y
M((string x)=>{return x.Length;});
y ver cuál, en su caso, nos da un error. En este caso, el primero da un error, este último compila sin error, por lo que esta es una conversión lambda legal y la resolución de sobrecarga tiene éxito. ¿Qué hacemos con el error? No podemos informarlo al usuario porque este programa está libre de errores.
Por lo tanto, lo que hacemos cuando vinculamos el cuerpo de una lambda es exactamente lo que dice: le decimos al reportero de errores "no informe sus errores al usuario; guárdelos en este búfer aquí". Luego vinculamos el lambda, restauramos el informe de errores a su estado anterior y miramos el contenido del buffer de error.
Podríamos evitar este problema completamente cambiando el analizador de expresiones para que devolviera los errores junto con el resultado, en lugar de convertir los errores en un efecto secundario relacionado con el estado. Entonces la necesidad de mutación del estado de informe de error desaparece por completo y ni siquiera tenemos que preocuparnos por ello.
Así que le animo a que vuelva a visitar su diseño. ¿Hay alguna manera de hacer que la operación que estás realizando no dependa del estado en el que estás mutando? Si es así, hazlo y no tendrás que preocuparte por cómo restaurar el estado mutado.
(Y, por supuesto, en nuestro caso nos hacemos desea restaurar el estado a una excepción. Si algo dentro del compilador lanza durante la unión lambda, queremos ser capaces de informar que para el usuario! Nosotros no hacemos quiere que el reportero de errores permanezca en el estado "suprimir los errores de informe".)
Software Transactional Memory? – shahkalpesh
es triste ver que tienes una muy buena reputación y todavía publicas toda la pregunta como título. – Shoban
¿Puede explicar en qué necesita específicamente esta construcción? Esto sucede para las variables pasadas por valor automáticamente, como al hacer llamadas a funciones, pero no estoy seguro de que sea eso lo que estás buscando. – GrayWizardx