while tipos qué programacion lenguaje infinitos for espacio ejemplos ciclos bucles bucle c# .net visual-studio bytecode compiler-optimization

c# - qué - tipos de ciclos en programacion



¿Se manejan explícitamente los bucles infinitos en.NET como un caso especial? (2)

El compilador no marca esto porque el final del método es inalcanzable . Eso no es un problema, solo es un problema si puede llegar al final del método (la llave de cierre) sin devolver un valor.

Esto no es una cuestión de optimización del compilador, es un caso de seguir las definiciones de accesibilidad establecidas en la especificación.

Tenga en cuenta que no necesita una declaración de retorno en absoluto ... este código es inútil, pero perfectamente válido:

public int EndlessLoop() { while (true) { } }

Hoy temprano, cuando estaba codificando un método y me di cuenta de que no estaba seguro de por qué el lenguaje que estaba implementando se compila. Si todo lo demás se abstrae, se vería algo como esto:

private int Example() { while (true) { if (some condition) { return 1; } } }

Tiene un bucle infinitamente explícito y un conjunto de condiciones dentro del bucle que hacen que el bucle finalice con una declaración de retorno. Ignoremos por el momento por qué estaba haciendo esto en lugar de verificar una condición de terminación en la cláusula while, ya que la respuesta es complicada e irrelevante. Lo que quiero saber es por qué el compilador no marca esto con un "No todas las rutas devuelven un valor ". error, ya que, estrictamente hablando, no todas las rutas devuelven un valor. El caso en el que el bucle while nunca se ingresa (lo que, por supuesto, nunca sucede) no devuelve nada.

Ahora, hay dos razones por las que puedo imaginar que suceda: este es un efecto secundario de la optimización que se está produciendo por otras razones, o este caso está siendo manejado explícitamente por el compilador para permitir este idioma. Mi instinto es que es probablemente el primer caso. No me sorprende en absoluto, por ejemplo, que esto compile:

private int Example2() { if (true) return 1; }

Porque el compilador ve una constante constante en el if, y optimiza el condicional de distancia. Sin embargo, realmente no entiendo por qué esto "arreglaría" el primer ejemplo.

Ah, y aún más extraño, si se está ejecutando una optimización que elimina el bucle, esto se compila:

private int Example3() { while (true) { if (false) { return 1; } } }

Pensaría que todo el bucle interno se optimizaría, eliminando todas las devoluciones válidas. ¿Qué está pasando realmente aquí a nivel de bytecode / compiler que hace que todo esto tenga sentido?


Para darle un caso de uso para este tipo de bucles infinitos, considere el siguiente código:

public int KeyboardChecker() { while (true) { if (KeyHasBeenPressed()) { HandleKeyPress(); } } }

A continuación, ejecuta este método en su propio subproceso, por lo que se maneja de forma asíncrona la entrada del teclado (este es el patrón de sondeo, por lo general es preferible tener un sistema de eventos en su lugar).

Puede imaginar hilos para devolver códigos de estado cuando se terminan, por lo que el valor de retorno del método es int. Sin embargo, dado que este hilo en particular nunca terminará, no es un problema en absoluto que el método no contenga ninguna declaración de retorno. Los diseñadores de C # sabían sobre estos casos de uso e hicieron legal el método anterior.

Tenga en cuenta que el problema general de averiguar si un método en particular siempre devolverá un valor es indecidible (es decir, no puede ser resuelto por ningún programa de computadora). Por lo tanto, el compilador de C # puede quejarse del código que siempre devolverá un valor (aunque nunca aceptará programas que no lo hacen):

public int DoWork() { // The compiler doesn''t figure out this will always be true. if (((int)Math.Sqrt(4)) == 2) { return 3; } // And therefore complains that not all code paths return a value for this method. }