2009-03-19 21 views
9

Las etiquetas y GOTO s se consideran malas prácticas y, que yo sepa, no hay ninguna razón para usarlo en C#.¿Cuál es el uso de las etiquetas en C#?

¿Cuál es el uso de las etiquetas en C#?

+3

Le dan a otros programadores un motivo para quejarse de tu código :-) –

+0

posible duplicado de [¿Alguien todavía usa \ [goto \] en C# y si ¿por qué?] (http://stackoverflow.com/questions/6545720/does-anyone-still-use-goto-in-c-sharp-and-if-so-why) –

Respuesta

19

No hay nada de malo con las etiquetas y los goto en sí mismos. El problema es que las personas tienden a abusar de ellos, lo que crea un problema.

El uso típico de una etiqueta

OperationStart: 
    if (!TrySomeOperation()) { 
    if (MaybeFixOperation()) { 
     goto OperationStart; 
    } 
    } 

Se necesitaría hacer algunas afirmaciones que no se podría llegar a un bucle infitite, pero teniendo en cuenta un conjunto razonable de las garantías de que no hay nada inherentemente malo con este código.

+0

Creo que este es el uso más común de goto. –

+5

"no hay nada intrínsecamente incorrecto con este código" que quiere decir excepto el hecho de que no es muy legible? si lo escribiste con: while (! TrySomeOperation() && MaybeFixOperation()) {} hace que sea mucho más obvio que estás (posiblemente infinitamente) bucleando. – Aiua

+5

La legibilidad está en el ojo del lector. Lo seguí bien. – Perchik

7

El hecho de que sean una práctica desacreditada, no significa que deba cerrar ninguna posibilidad de usarlos. Si bien es posible que en realidad nunca sean necesarios, ocasionalmente son la mejor manera de hacerlo.

2

Creo que fue una decisión de marketing ..

Microsoft quiere todo tipo de desarrolladores que utilizan el lenguaje C#, y si se agrega etiquetas, que hace de transición para algunos programadores más fácil. También hace que sea más fácil transferir el código antiguo a su idioma ...

+0

Para el registro: No soy un enemigo de MS .. Estoy amando a C# tanto como al próximo chico ... y creo que fue un movimiento inteligente agregar etiquetas y declaraciones goto ... – Arcturus

0

Lo leí en alguna parte, ir en la mayoría de los casos debería usarse para saltar hacia adelante, por lo que lo más probable es para terminar el ciclo y continuar el ciclo externo desde no hay bucles etiquetados en C# (a diferencia de Java). Y hay algunos algoritmos que se pueden expresar elegantemente con goto que hacerlo de forma estructurada.

+0

Esta es la forma en que uso los gotos. bucles, a veces es más fácil simplemente ir a una etiqueta, en su lugar de intentar descubrir cómo salir de ese bucle. – Perchik

0

A veces un 'goto' bien colocado es más elegante/legible que otras técnicas. Poner 'goto's cuando no son necesarios es ciertamente una mala práctica. Como siempre, cada situación debe juzgarse con cuidado.

Por ejemplo, 'goto's puede ser agradable cuando su función necesita limpieza en caso de que falle. Coloca una etiqueta al final de la función, donde realiza la limpieza, luego 'goto' en caso de falla.

Sin embargo, los "goto" se han vuelto menos útiles en C# que en C. Por ejemplo, el uso adecuado del manejo de excepciones puede obviar la necesidad de 'goto' en algunos escenarios.

0

El uso de etiquetas es para admitir goto. Tan malo como goto puede ser, si tiene goto en el idioma, entonces necesita etiquetas. Sin goto, las etiquetas son realmente inútiles en C#.

6

Cuando se está implementando un pequeño finite state machine puede utilizar una etiquetapara cada estado y Goto para transiciones de estado. Este es uno de los métodos estándar para implantar máquinas de estado finito y puede conducir a un código claro, siempre que haya un diagrama de la máquina de estados en un documento al que apuntan los comentarios del código.

A veces, el dominio del problema contiene muchos machiens de estado (por ejemplo, los protocolos de telecomunicaciones se definen a menudo por máquinas de estados finitos), la mayoría de las veces no se ve la máquina de estados finitos a menudo.

Gotos y etiquetas también son muy útiles para el código generado por máquina, si está escribiendo un compilador simple que da salida a C# puede ser muy contenta de ellos.

+0

Los DFA se usan bastante, en general se usan en tokenizadores y analizadores sintácticos. Este enfoque llevaría a métodos masivos ... Usted sabe que si tiene un método muy grande en IL, no será optimizado por el tiempo de ejecución de .NET, ¿verdad? Por diversas razones, generalmente es mejor que un DFA compile un patrón de estado si me lo pregunta, incluso si se trata de un código generado por la máquina. – atlaste

2

Las etiquetas sin goto son inútiles, no hacen nada.

El uso de goto se considera una mala práctica. Sin embargo, hay un caso en el que no se puede evitar: salir de bucles anidados:

foreach(...) { 
    foreach(...) { 
    if(...) { 
     goto OuterLabel; 
    } 
    } 
} 
OuterLabel: 

En tal caso, mediante la instrucción break acaba de romper el bucle más interior.

+1

¿Por qué no poner las dos miradas foreach dentro de su propio método, entonces solo puede usar una declaración de retorno para salir? La mayoría de los ejemplos de goto que he visto están en métodos largos, no me gustan los métodos largos. –

+0

De acuerdo, usar un método separado es un buen enfoque, porque la declaración 'return' puede salir del método completo. –

+5

Algunas personas (yo incluido) no me gusta crear métodos solo para crearlos. – Perchik

1

Es difícil hacer declaraciones sin ellas.

+0

¿Lo es? Me parece que puedo manejar ... ¿Puedes dar un ejemplo? – Blorgbeard

+0

El caso y las declaraciones predeterminadas son etiquetas. Puede ver esto con: switch (x) { case 1: if (oneEqualsTwo) goto case 2; break; case 2: break; } Esto se hace más claro en las especificaciones de ECMA para C#: http://www.csharpfriends.com/Spec/index.aspx?specID=15.7.2.htm – mancaus

0

Si bien, en principio, creo que hay usos legítimos para la declaración goto, en la práctica, he estado desarrollando en C# desde que fue lanzado por primera vez y yo no sabía que tenía goto un comunicado hasta ahora.

2

Los generadores de código a veces usan etiquetas y gotos. Puede simplificar la lógica de generación de código en algunos casos. Las declaraciones Goto generalmente se evitan por razones de legibilidad, pero si el código no está destinado a ser leído, entonces ese es un punto discutible.

También he visto casos en los que un decompilador se confunde lo suficiente con la IL y genera declaraciones goto en lugar de la secuencia bien elaborada de instrucciones que un humano habría conjurado. Si las declaraciones de goto no eran legales, el descompilador podría tener que despejar completamente en esa sección de código. De esta forma, al menos, puede generar algo que se puede activar de forma circular.

0

If (audience.LikesGoTo == true) { goto LabelThatSupportGoTo; } else { goto LabelForRejectGoTo; }

+0

¿Pensó en usar [este artículo] (http: //www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_Harmful.html) para LabelForRejectGoTo. – Ben

2

¿Por qué está allí?

La razón es bastante simple. Assembler e IL no admiten instrucciones avanzadas como for, do, break, continue y while. Implícitamente, el código que se repite (o más generalmente: ramas) se compila en las ramas. goto y label es una rama muy literal.

Tenga en cuenta que simplemente no puede implementar todos los artilugios que se me ocurren fácilmente sin un 'goto'- a pesar de que generalmente hay mejores alternativas (en este punto me gustaría señalar que hay patrones de diseño como el State pattern).

Si diseña un lenguaje como C#, que es una especie de "ensamblador de alto nivel para IL", tiene sentido admitir al menos todo lo que hay en IL. Aquí, branch/label es la construcción de bajo nivel, y goto/label es la proyección C# (con el alcance agregado como constructo de alto nivel).

Desde el Punto de vista del compilador

Eventualmente, si se desciende a cómo funciona un compilador, hay una diferencia en código predecible y impredecible código. La parte optimizadora de un compilador gasta una gran cantidad de esfuerzo para normalizar las construcciones que está usando en su código. Una vez normalizado, se optimiza usando patrones.

Aquí radica el problema. Si tiene un bucle while, un bucle for o un bucle foreach, definitivamente generará un patrón normalizado. Después de todo, los loops son lo más importante en su código que puede optimizarse. Sin embargo, si está utilizando ramas extrañas, no se optimizará, simplemente porque no se normalizará en un patrón estandarizado y, por lo tanto, no será recogido por el patrón de coincidencia.

Este comentario no trata solo sobre la previsibilidad de los patrones de código, sino también sobre la previsibilidad del flujo de datos. Nuevamente, si es predecible, su compilador puede hacer más que si no lo hace. En varios casos, construcciones como break y continue también darán lugar a ramas más impredecibles; etiquetas y goto lo llevarán allí más fácilmente. El resultado es el mismo: su rendimiento sufrirá si esto ocurre.

Por lo tanto, si bien es cierto que todos los compiladores cambian los bucles en las ramas de un formulario específico. El compilador de IL es un compilador de SSA, al igual que LLVM. Este video de Chandler explica una o dos cosas sobre cómo funciona esto: https://www.youtube.com/watch?v=FnGCDLhaxKU

Cuestiones relacionadas