remarks generate example c# exception out

generate - params comments c#



Fuera de parĂ¡metros y excepciones. (5)

Bastante, ese es un aspecto de lo out significa out ; En primer lugar, tenga en cuenta que el out no existe realmente, solo necesitamos considerar ref ( out es simplemente ref con algunos ajustes de "asignación definida" en el compilador). ref significa "pasar la dirección de esto": si cambiamos el valor a través de la dirección, entonces eso se muestra de inmediato , es, después de todo, la actualización de la memoria en la pila de Main . No puede abstraer esto (retrasar la escritura) porque el valor podría ser, por ejemplo, una estructura sobredimensionada que usa ref Específicamente con el propósito de evitar copiarlo en la pila (un enfoque utilizado ampliamente en XNA, etc.).

Digamos que tengo el siguiente código:

static void Fjuk(out string str) { str = "fjuk!"; throw new Exception(); } static void Main(string[] args) { string s = null; try { Fjuk(out s); } catch (Exception) { Console.WriteLine(s ?? ""); } }

Cuando lo probé, s ha sido inicializado a "fjuk!" cuando se usa en el bloque catch .
¿Esto está garantizado por la especificación o depende de la implementación? (He buscado en la especificación C # 3 pero no pude encontrarlo)


De la sección Especificación de lenguaje C # 5.1.6 Parámetros de salida

Tras la finalización normal de una invocación de miembro o delegado de función, cada variable que se pasó como parámetro de salida se considera asignada en esa ruta de ejecución.

En otras palabras

  • out parámetros de out siempre se asignan.
  • Se sobrescribe cualquier valor anterior.
  • pero si la función lanza una excepción, el compilador asume que no están asignados.

En la práctica

  • Nunca debes preocuparte por esto.
  • Si intenta usar una variable no asignada, el compilador generará un error.
  • Por lo tanto, los parámetros en C # son completamente seguros : si se compilan, funcionan.

Está garantizado desde la perspectiva de Fjuk pero no de Main .

En Fjuk la excepción se Fjuk después de que se establece el parámetro. Si bien el compilador, el jitter y la CPU pueden reordenar, no se reordenarán de manera tal que el orden observado por un solo hilo cambie. Dado que un solo hilo podría "notar" si el parámetro no se configuró antes de que se lanzara la excepción, se garantiza que el parámetro se establezca.

Sin embargo, en Main , no tenemos conocimiento de los detalles de la Fjuk de Fjuk , por lo que cuando el compilador analiza Main , no puede depender de eso. Por lo tanto, en la variación donde no asignamos un valor a s antes de la llamada:

static void Main() { string s; try { Fjuk(out s); Console.WriteLine(s ?? "");//fine } catch (Exception) { Console.WriteLine(s ?? "");//compiler error } Console.WriteLine(s ?? "");//compiler error }

El primer intento de usar s inmediatamente después de la llamada a Fjuk está bien, porque solo se puede llegar si Fjuk tuvo éxito, y si Fjuk tuvo éxito, entonces se debe asignar s. Sin embargo, en el segundo y tercer caso, es posible llegar a esas líneas sin que Fjuk éxito, y como no se puede saber mediante el análisis de Main si se puede lanzar una excepción antes de que se establezca s deben prohibir los usos de s .


Si el método lanza una excepción, no se garantiza que el parámetro de salida se establezca. Si el método sale sin una excepción, se garantiza que el parámetro de salida se establecerá.

En su caso, el método siempre establecerá el parámetro de salida, pero el compilador no analiza el código del método de esa manera. Si el método sale con una excepción, el parámetro de salida todavía no se considera definitivamente establecido.

Su código en el controlador de excepciones no se basa en la variable establecida por la llamada al método, ya que está configurando la variable cuando se crea. Si no configura la variable cuando se crea, el controlador de excepciones no puede usarla, porque no se garantiza que se establezca:

string s; try { Fjuk(out s); Console.WriteLine(s); // here the variable is guaranteed to be set } catch (Exception) { Console.WriteLine(s); // here it''s not, so this won''t compile }


Está "garantizado" porque out parámetro cambia el valor con la memory address de memory address del parámetro.

La palabra clave out hace que los argumentos se pasen por referencia. Esto es similar a la palabra clave ref, excepto que ref requiere que la variable se inicialice antes de pasar.

de MSDN