2009-03-03 7 views
8

Comprendo los punteros y la rara necesidad de usarlos en el código C#. Mi pregunta es: ¿cuál es el razonamiento detrás de tener que declarar explícitamente "inseguro" en un bloque de código? Además, ¿por qué debe cambiarse una opción del compilador para permitir el código "inseguro"?C#: Ventaja de indicar explícitamente la opción "insegura"/compilador

línea de base: Lo que en el CLR (o las especificaciones del lenguaje) lo hace por lo que no se puede simplemente utilizar punteros siempre que queramos (como C y C++) sin tener que escribir "inseguro" y cambie la opción de compilador ?

Para aclaración: sé lo que es el código "inseguro" y "seguro". Es solo una cuestión de por qué debemos hacer todo el trabajo extra (vale, no tanto) solo para poder utilizar estas características.

Respuesta

9

Hay una entrevista con C# Creator Anders Hejlsberg que toca el tema here. Básicamente, exactamente lo que dijo @Marc Gravell: tipo de seguridad primero, inseguridad por declaración explícita.

Para responder a su pregunta: nada en el CLR lo impide; es un idioma idiomático diseñado para permitirle trabajar con guantes de seguridad cuando se trata de tipos. Si quieres quitarte los guantes, es tu elección, pero tienes que elegir activamente quitarte los guantes.

Editar:

Como aclaración: Sé lo "inseguro" y "seguro" es el código. Es solo una pregunta de por qué debemos hacer todo el trabajo adicional (vale, no ESO de más) solo para poder utilizar estas funciones.

Como mencioné en la entrevista que enumeré, fue una decisión de diseño explícita. C# es esencialmente una evolución de Java y en Java, no tienes punteros en absoluto. Pero los diseñadores querían permitir punteros; sin embargo, debido a que C# normalmente atraerá a los desarrolladores de Java, consideraron que sería mejor si el comportamiento predeterminado fuera similar a Java, es decir, sin punteros, al tiempo que permitiera el uso de punteros por declaración explícita.

Así que el "trabajo extra" es deliberado para obligarlo a pensar en lo que está haciendo antes de hacerlo. Al ser explícito, te obliga a al menos considerar: "¿Por qué estoy haciendo esto? ¿Necesito un realmente cuando un tipo de referencia será suficiente?"

7

Se trata principalmente de ser verificable. Al indicar unsafe, los guantes están apagados; el sistema ya no puede garantizar que su código no se vuelva loco. En la mayoría de los casos, es muy conveniente permanecer en la zona segura.

Esto se vuelve más notable con la confianza parcial (complementos, etc.), pero sigue siendo valioso en el código normal.

+0

Básicamente, ¿es MS tratando de evitar que cometamos los mismos errores que en C++? – Inisheer

+1

Desde MS: el código C# que realiza llamadas de API de bajo nivel, usa aritmética de puntero o lleva a cabo alguna otra operación desagradable, tiene que colocarse dentro de bloques marcados con la palabra clave insegura. – VBNight

+0

# De MS: En algunos casos, un código inseguro puede aumentar el rendimiento de una aplicación al eliminar las comprobaciones de límites de la matriz. – VBNight

1

Así que es inmediatamente obvio qué código no se ejecutará en los servicios web sin permisos elevados, etc.

1

Cultivar buenos hábitos de seguridad &. Siempre que use un bloque inseguro en un ensamblaje, se exigirá un permiso NativeCode de la pila. Por supuesto, esto podría hacerse de manera implícita, pero ¿no podríamos simplemente eliminar la palabra clave privada por completo? Creo que es bueno forzar a los desarrolladores a requerir específicamente un código inseguro antes de que puedan usarlo.

2

Cuando utiliza un bloque inseguro, tiene el efecto de hacer que el código no se pueda verificar. Esto requiere ciertos permisos para ejecutarse y es posible que no desee permitirlo en su salida (especialmente si se encuentra en un entorno de origen compartido), por lo que hay un cambio en el compilador para no permitirlo.

2

Piénselo desde el punto de vista opuesto: como no está marcado como inseguro, puede inferir que la mayoría del código es "seguro" por defecto. Entonces, ¿qué significa ser "seguro"? Para el código .Net, esto incluye (pero no se limita a):

  • El recolector de basura puede hacer negocios como de costumbre.
  • Las referencias a un tipo específico harán referencia a objetos de ese tipo (o nulo).
  • Se garantiza que el código cumple con los requisitos de confianza/seguridad de .Net.
  • El código está matemáticamente probado de no tocar directamente la memoria fuera de su propio dominio de aplicación. Puede parecer trivial, pero imagínese si tiene múltiples AppDomains en la misma aplicación. El programador puede tratarlos con confianza como lógicamente separados.

Cada vez que utiliza punteros tiene la oportunidad de romper cualquiera de esas garantías. Por lo tanto, marcar el código como inseguro deja esas protecciones.

1

La diferencia más significativa entre el código seguro y el inseguro es que el recolector de basura de .net no puede acceder al código inseguro. Automatic GC es una gran parte de la lengua vernácula de .net y, cuando vas más allá de sus límites, cambias mucho de lo que se puede suponer acerca de tu código.

Los punteros en particular permiten la creación de objetos en el montón sin referencias de GC. Esto conduce a otra razón excelente para requerir que el código se marque como "inseguro". Hace que sea más fácil reducir el origen de una fuga de memoria cuando te das cuenta de que tienes una.

3

En realidad, el CLR no exige ningún tipo de cambio o palabra clave insegura. De hecho, C++/CLI (el lenguaje C++ que se ejecuta bajo el CLR) no tiene dicho interruptor/inseguro, y los punteros se pueden utilizar libremente en el CLR.

Por lo tanto, volvería a formular su pregunta como "¿Por qué C# requiere el uso de/inseguro antes de que se puedan utilizar los punteros?" Y la respuesta a esa pregunta es como se indica en otras respuestas dadas aquí: para ayudar al usuario a tomar una decisión consciente de perder la capacidad de ejecutar en cualquier modo que no sea el modo de confianza total en el CLR. C++ casi siempre requiere plena confianza en el CLR, y C# puede cada vez que llamas al código que requiere plena confianza o cuando usas punteros.

+0

Exactamente. Reformulé la parte del "resultado final" más temprano. Uso C++/CLI con bastante frecuencia, y de hecho es la razón por la que hago esta pregunta sobre C#. – Inisheer

2

En resumen, .NET quiere que exprese su intención.

Claro, el compilador podría deducir la necesidad del indicador "inseguro". Pero los diseñadores quieren que sea una decisión deliberada.

Para mí, es similar a una serie de requisitos sintácticos en C#:

  • ningún caso el interruptor sin descanso
  • sin acceso a nivel de "secciones" (como el "público:" marcador en C++)
  • no hay campos de clase utilizando "var"

El patrón es que no se debe mover o cambiar una cosa y sin querer afectar a otro. Dentro de lo razonable, quieren evitar que "te pegues un tiro en el pie".

Muchas respuestas excelentes e informativas aquí — quizás esto va más a su pregunta.

Cuestiones relacionadas