Pregunta

En C ++ hay muchas maneras en que puedes escribir código que compila, pero produce Comportamiento indefinido (Wikipedia). ¿Hay algo similar en C#? ¿Podemos escribir código en C# que se compila, pero tiene un comportamiento indefinido?

¿Fue útil?

Solución

Como otros han mencionado, casi cualquier cosa en el bloque "inseguro" puede producir un comportamiento definido por la implementación; El abuso de bloques inseguros le permite cambiar los bytes de código que componen el tiempo de ejecución en sí y, por lo tanto, todas las apuestas están desactivadas.

El caso de la esquina de la división entera tiene un comportamiento definido por implementación.

Lanzar una excepción y nunca atraparla causa un comportamiento definido por la implementación: termine el proceso, inicie un depurador, etc.

Hay una serie de otras situaciones en C# donde nos vemos obligados a emitir un código que tiene un comportamiento determinado de implementación. Por ejemplo, esta situación:

http://blogs.msdn.com/ericlippert/archive/2006/04/06/odious-ambiguue-overloads-tart-two.aspx

Sin embargo, las situaciones en las que un programa de C# seguro y bien se portó el comportamiento definido por la implementación debería ser bastante raro.

Otros consejos

¡Sí! ¡Hay, incluso en un contexto seguro! (Bueno, se define la implementación para estar indefinido, al menos)

Aquí hay uno de Marek Safar y Vsadov en el Problemas de Roslyn. Hay un desajuste entre C# y la CLI con respecto a bool.

C# cree que solo hay un tipo de true, y un tipo de false.

CLI cree que false es un byte que contiene 0, y todos los demás valores son true.

Esta discrepancia significa que podemos coaccionar c# para hacer alguno un (marginalmente) interesante cosas cosa:

//non-standard bool
//We're setting a bool's value to a byte value of 5.
var a = new bool[1];
Buffer.SetByte(a, 0, 5);

//non-standard bool
//We're setting a bool's value to a byte value of 10.
var b = new bool[1];
Buffer.SetByte(b, 0, 10);

//Both are true.
Console.WriteLine(a[0]);
Console.WriteLine(b[0]);

//But they are not the same true.
Console.WriteLine(a[0] == b[0]);

Las salidas anteriores:

true

true

false

Curiosamente, el depurador no está de acuerdo (¿debe evaluar la verdad de manera diferente?)

enter image description here

De todos modos, la conclusión a la que parece haber llegado el equipo C# es (énfasis agregado):

Es decir, el idioma permanecerá completamente despreocupado sobre bools no estándar. La implementación particular (como en MS C# en CIL) reconocerá la existencia de bools no estándar y especificará su comportamiento como indefinido

Mirando el wiki, las situaciones en las que ocurre el comportamiento indefinido no están permitidos o arrojan una excepción en C#.

Sin embargo, en código inseguro, creo que el comportamiento indefinido es posible, ya que eso le permite usar punteros, etc.

Editar: parece que tengo razón: http://msdn.microsoft.com/en-us/library/aa664771%28vs.71%29.aspx

Tiene un ejemplo de comportamiento indefinido en c#

Según el documento ECMA-334 (p. 473):

Un programa que no contiene ningún hecho del modificador inseguro no puede exhibir ningún comportamiento indefinido.

Eso promueve 'definido por la implementación' al peor de los casos, ver la respuesta de Eric Lippert.

Muchos y subprogramas tienen requisitos que se pueden resumir como:

  1. Cuando se les dan datos válidos, produzca una salida válida.

  2. Abstenerse de lanzar misiles nucleares o negar las leyes del tiempo y la causalidad, incluso cuando se les da una entrada no válida.

Uno de los principales objetivos de diseño de los idiomas Java y .NET es que a menos que el código utilice ciertos que se marcan como "inseguros", generalmente no se requiere un esfuerzo particular para cumplir con la segunda restricción anterior [aunque algunos comportamientos relacionados con la recolección de basura y Finalize Puede ser un poco extraño desde el punto de vista del tiempo/causalidad, se pueden describir como excepciones a las reglas normales de causalidad, en lugar de una revocación total de ellas]. Esa situación es muy diferente de la situación en C, donde muchos tipos de errores dependientes de datos (por ejemplo, desbordamiento entero) pueden dar como resultado que los compiladores se comporten de manera arbitraria, incluida la fabricación de cualquier suposición que sea necesario para evitar el desbordamiento. Los tipos verdaderamente horribles de comportamiento indefinido que se fomentan en la filosofía Hipermoderna C no existen en C# u otros idiomas .NET fuera de bloques "inseguros".

Realmente no en el sentido de la wiki exactamente, pero supongo que el ejemplo más obvio que me viene a la mente es simplemente escribir algún código enhebrado, pero entonces es así en cualquier idioma.

En general diría que no.

Use la variable automática antes de que se inicialice.

Todas las variables deben ser inicializadas. Si no se produce una excepción.

División por cero

Se lanza la excepción.

Indexando una matriz fuera de los límites

Se lanza la excepción

Como señaló Aequitarum Custs, puede usar un código inseguro. Por otra parte, esto no es realmente C#, está optando explícitamente del entorno C#.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top