c# unchecked-conversion

c# checkbox checked



desactivada-keyword en C# (5)

Tal vez estoy en lo básico, pero todavía estoy estudiando esta cosa de C # en la escuela. Entiendo que si agrego 1 al entero de valor máximo, cuál es de 32 bits, el resultado será negativo. Leí que C # ofrece palabras clave marcadas y no marcadas para manejar los desbordamientos. La palabra clave marcada es algo que he encontrado útil, pero ¿qué hay de una palabra clave no verificada? Realmente no puedo encontrar un uso no muy útil para el bloque sin marcar con clave. ¿Hay alguna? ¿En qué se diferencian los dos enfoques siguientes de cada uno?

using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace Practice_6 { class Program { static void Main(string[] args) { int value = Int32.MaxValue; value++; //Approach 1 to make a decision if (value > Int32.MaxValue) { //Do something } value = Int32.MaxValue; //Approach 2 to make a decision unchecked { value++; //Do something } //What''s the difference between these two approaches to handle overflow? } }


ACTUALIZACIÓN: Esta pregunta fue el tema de mi blog en abril de 2015 ; Gracias por la interesante pregunta!

Tu primera pregunta es:

La palabra clave checked es útil, pero ¿qué hay de la palabra clave unchecked ? Realmente no puedo encontrar un uso para ello. ¿Hay alguna?

El equipo de diseño de C # no tiene la costumbre de agregar características que no tienen ninguna utilidad para el lenguaje. (Con la notable excepción del operador unary plus, el operador más inútil del mundo).

La palabra clave no seleccionada tiene dos casos de uso principales.

Primero, la aritmética de enteros constantes siempre se verifica por defecto . Esto puede ser irritante. Supongamos, por ejemplo, que tiene algún código de interoperabilidad y desea crear una constante para HRESULT E_FAIL:

const int E_FAIL = 0x80004005;

Eso es un error porque ese número es demasiado grande para caber en un int . Pero tal vez no quieras usar una uint . Podrías pensar bien, solo diré

const int E_FAIL = (int)0x80004005;

Pero eso también es ilegal porque la aritmética constante, incluidas las conversiones, siempre se verifica de forma predeterminada.

Lo que tienes que hacer es desactivar la aritmética constante marcada mediante

const int E_FAIL = unchecked((int)0x80004005);

En segundo lugar, la aritmética predeterminada para las matemáticas de enteros no constantes en C # no está marcada, porque es más rápida y porque eso es lo que hacen muchos otros lenguajes similares. Sin embargo, C # le permite cambiar la aritmética predeterminada a la matemática de enteros no constante a través de un indicador de compilador. Si lo ha hecho, y necesita volver a desactivarlo temporalmente, entonces tiene que usar la sintaxis de expresión o bloque unchecked marcar.

Un tercer caso de uso es usar el bloque sin marcar como una forma de código de auto-documentación, para decir "Soy consciente de que la operación que estoy haciendo aquí puede desbordarse, y eso está bien para mí". Por ejemplo, a menudo escribo algo como:

int GetHashCode() { unchecked { int fooCode = this.foo == null ? 0 : this.foo.GetHashCode(); int barCode = this.bar == null ? 0 : this.bar.GetHashCode(); return fooCode + 17 * barCode; } }

"Sin marcar" enfatiza al lector que esperamos que la multiplicación y la adición de códigos hash puedan desbordarse, y que esto está bien.

Tu segunda pregunta es:

¿Cuál es la diferencia entre estos dos enfoques para manejar el desbordamiento?

Buena pregunta.

Si en su contexto marcado quiere decir: espero que la aritmética esté siempre dentro de los límites; si no es así, mi programa tiene un error grave y debe terminarse antes de que cause más daño al mundo , por lo que no debería hacer ninguna comprobación de desbordamiento, porque no hay desbordamientos. Cualquier excepción debe terminar el programa; el contexto verificado es simplemente hacer que el tiempo de ejecución funcione para verificar la exactitud de su código.

Si en su contexto marcado quiere decir que necesito que la aritmética esté dentro de los límites, pero obtuve estos datos de una fuente no confiable y soy demasiado perezoso para verificar el rango, entonces debería detectar la excepción. Sin embargo , la mejor práctica sería hacer una verificación de rango y dar un error más significativo si los datos están fuera de rango, que hacer que el tiempo de ejecución note el problema y lanzar una excepción de desbordamiento. Recomiendo encarecidamente la verificación de rango en lugar de atrapar una excepción; no seas perezoso


Cambia tus códigos a:

int value = int.MaxValue; unchecked { value++; } Console.WriteLine(value); value = int.MaxValue; checked { value++; // this will raise OverflowException }

y verás la diferencia.


Desde MSDN, la razón para usar sin marcar sería la siguiente

Debido a que la verificación del desbordamiento lleva tiempo, el uso de código no verificado en situaciones donde no hay peligro de desbordamiento puede mejorar el rendimiento. Sin embargo, si es posible un desbordamiento, se debe utilizar un entorno comprobado.


No estoy muy seguro de las implicaciones de rendimiento de checked y unchecked . En teoría, unchecked debería ser más eficaz y es el contexto predeterminado. A menos que se coloque alrededor de los límites de los tipos de enteros para algún tipo de algoritmo especial / lógica de negocios, etc., el uso de los checked raramente es necesario / útil / legible.

Como dije, el contexto predeterminado unchecked está unchecked , ¿por qué necesita una palabra clave unchecked ? Una cosa podría ser ser explícito sobre el tipo de contexto en el que hay un alto uso de contextos marcados. La otra es usar el contexto unchecked marcar dentro del contexto checked :

checked { int a = 5 + 1231; unchecked { a += 221; } }

Su pregunta podría ser por qué el contexto predeterminado no está marcado. Supongo que es una elección de diseño por parte de Microsoft.

Su diferencia es que el contexto checked comprueba si hay un desbordamiento para cada operación aritmética y genera una excepción si hay un desbordamiento.


No se debe esperar que el código escrito correctamente dependa de si un proyecto se compila con marcado o no como predeterminado. Código en el que el comportamiento aritmético de ajuste inesperado podría suponer un riesgo para la seguridad o la estabilidad del sistema debe realizarse en un contexto checked . El código que se basa en el comportamiento aritmético de ajuste se debe hacer en un contexto unchecked marcar. El código de propósito general en el que no se espera que ocurran desbordamientos aritméticos, pero que tendrían consecuencias limitadas si lo hicieran, debería compilarse usando la configuración a nivel de proyecto. La configuración del nivel del proyecto se puede establecer como activada o desactivada como una compensación entre la velocidad de ejecución y la captura oportuna de errores.

Si no se producen desbordamientos inesperados en ninguna parte, el código se ejecutará más rápido en el modo sin marcar. Sin embargo, si algunos cálculos arrojan valores falsos y no está claro por qué, la recompilación con la verificación de desbordamiento habilitada puede ayudar. Hará que el código se ejecute más lentamente, pero quedará atrapado en el primer cálculo erróneo. Sin embargo, cambiar el proyecto al modo comprobado para tal propósito, solo será posible si las partes del proyecto que se basan en el comportamiento aritmético de ajuste se realizan en un contexto explícito unchecked marcar. De lo contrario, cambiar los modos de nivel de proyecto simplemente romperá el programa por completo.