InteroperabilidadEditar
Dado que los sistemas informáticos suelen requerir la interacción entre aplicaciones más nuevas y más antiguas, .NET Framework proporciona medios para acceder a funciones implementadas en programas más nuevos y más antiguos que se ejecutan fuera del entorno .NET. El acceso a los componentes del Modelo de Objetos de Componentes (COM) se proporciona en los espacios de nombres System.Runtime.InteropServices
y System.EnterpriseServices
del framework. El acceso a otras funciones se realiza a través de los servicios de invocación de la plataforma (P/Invoke). El acceso a las funciones .NET desde las aplicaciones nativas se realiza a través de la función P/Invoke inversa.
Independencia del lenguajeEditar
.NET Framework introduce un Sistema de Tipos Comunes (CTS) que define todos los tipos de datos y construcciones de programación posibles soportados por CLR y cómo pueden o no interactuar conforme a la especificación CLI. Gracias a esta característica, .NET Framework admite el intercambio de tipos e instancias de objetos entre bibliotecas y aplicaciones escritas con cualquier lenguaje .NET conforme.
Seguridad de tipos
El CTS y el CLR utilizados en .NET Framework también aplican la seguridad de tipos. Esto evita los castings mal definidos, las invocaciones de métodos erróneos y los problemas de tamaño de memoria al acceder a un objeto. Esto también hace que la mayoría de los lenguajes CLI estén tipados estáticamente (con o sin inferencia de tipos). Sin embargo, a partir de .NET Framework 4.0, el Dynamic Language Runtime extendió el CLR, permitiendo que los lenguajes dinámicamente tipados fueran implementados sobre el CLI.
Portabilidad
Aunque Microsoft nunca ha implementado el framework completo en ningún sistema excepto Microsoft Windows, ha diseñado el framework para que sea multiplataforma, y hay implementaciones disponibles para otros sistemas operativos (ver Silverlight y § Implementaciones alternativas). Microsoft presentó las especificaciones de CLI (que incluye las bibliotecas de clases principales, CTS y CIL), C# y C++/CLI a Ecma International (ECMA) y a la Organización Internacional de Normalización (ISO), lo que las convierte en normas oficiales. Esto hace posible que terceros creen implementaciones compatibles del framework y sus lenguajes en otras plataformas.
SeguridadEdit
.NET Framework tiene su propio mecanismo de seguridad con dos características generales: Seguridad de Acceso al Código (CAS), y validación y verificación. CAS se basa en pruebas que se asocian a un ensamblaje específico. Normalmente la evidencia es el origen del ensamblaje (si está instalado en la máquina local o ha sido descargado de Internet). CAS utiliza las pruebas para determinar los permisos concedidos al código. Otro código puede exigir que se conceda al código de llamada un permiso específico. La demanda hace que el CLR realice un paseo por la pila de llamadas: se comprueba cada ensamblaje de cada método de la pila de llamadas para ver si tiene el permiso requerido; si a algún ensamblaje no se le concede el permiso, se lanza una excepción de seguridad.
El bytecode CIL gestionado es más fácil de someter a ingeniería inversa que el código nativo, a menos que esté ofuscado. Los programas de descompilación de .NET permiten a los desarrolladores sin conocimientos de ingeniería inversa ver el código fuente que hay detrás de los ensamblados .NET no ofuscados. En cambio, las aplicaciones compiladas en código máquina nativo son mucho más difíciles de someter a ingeniería inversa, y el código fuente casi nunca se produce con éxito, principalmente debido a las optimizaciones del compilador y a la falta de reflexión. Esto genera preocupación en la comunidad empresarial por la posible pérdida de secretos comerciales y la elusión de los mecanismos de control de licencias. Para mitigar esto, Microsoft ha incluido Dotfuscator Community Edition con Visual Studio .NET desde 2002. También existen herramientas de ofuscación de terceros de proveedores como VMware, V.i. Labs, Turbo y Red Gate Software. Las herramientas de encriptación a nivel de método para el código .NET están disponibles en proveedores como SafeNet.
Gestión de la memoriaEditar
CLR libera al desarrollador de la carga de gestionar la memoria (asignar y liberar cuando se hace); se encarga de la gestión de la memoria por sí mismo detectando cuándo se puede liberar la memoria de forma segura. Las instancias de los tipos .NET (objetos) se asignan desde el heap gestionado; un pool de memoria gestionado por CLR. Mientras exista una referencia a un objeto, que puede ser directa o a través de un gráfico de objetos, se considera que el objeto está en uso. Cuando no existe ninguna referencia a un objeto, y no puede ser alcanzado o utilizado, se convierte en basura, elegible para su recolección.
.NET Framework incluye un recolector de basura (GC) que se ejecuta periódicamente, en un hilo separado del hilo de la aplicación, que enumera todos los objetos inutilizables y reclama la memoria asignada a ellos. Se trata de un recolector de basura no determinista, de compactación y de marcado y barrido. El GC sólo se ejecuta cuando se ha utilizado una cantidad determinada de memoria o cuando hay suficiente presión de memoria en el sistema. Dado que no se garantiza cuándo se alcanzan las condiciones para recuperar la memoria, las ejecuciones de GC son no deterministas. Cada aplicación .NET tiene un conjunto de raíces, que son punteros a objetos en el heap gestionado (objetos gestionados). Estos incluyen referencias a objetos estáticos, objetos definidos como variables locales o parámetros de métodos actualmente en alcance, y objetos referidos por registros de la CPU. Cuando la GC se ejecuta, pone en pausa la aplicación y luego, para cada objeto referido en la raíz, enumera recursivamente todos los objetos alcanzables desde los objetos raíz y los marca como alcanzables. Utiliza los metadatos de la CLI y la reflexión para descubrir los objetos encapsulados por un objeto, y luego los recorre recursivamente. A continuación, enumera todos los objetos de la pila (que se asignaron inicialmente de forma contigua) utilizando la reflexión. Todos los objetos no marcados como alcanzables son basura. Esta es la fase de marcado. Dado que la memoria retenida por la basura no tiene importancia, se considera espacio libre. Sin embargo, esto deja trozos de espacio libre entre los objetos que inicialmente eran contiguos. Los objetos se compactan entonces para que el espacio libre en el montón gestionado vuelva a ser contiguo. Cualquier referencia a un objeto invalidada por el movimiento del objeto es actualizada por GC para reflejar la nueva ubicación. La aplicación se reanuda una vez finalizada la recolección de basura. La última versión de .NET framework utiliza la recolección de basura concurrente junto con el código de usuario, lo que hace que las pausas sean imperceptibles, ya que se realiza en segundo plano.
El recolector de basura utilizado por .NET Framework también es generacional. A los objetos se les asigna una generación. Los objetos recién creados se etiquetan como Generación 0. Los objetos que sobreviven a una recolección de basura se etiquetan como Generación 1. Los objetos de la Generación 1 que sobreviven a otra recolección son de la Generación 2. El framework utiliza objetos de hasta Generación 2. Los objetos de mayor generación se recogen con menos frecuencia que los de menor generación. Esto aumenta la eficiencia de la recolección de basura, ya que los objetos más antiguos tienden a tener una vida más larga que los objetos más nuevos. Al ignorar los objetos más antiguos en la mayoría de las ejecuciones de recolección, se necesitan menos comprobaciones y operaciones de compactación en total.
RendimientoEdit
Cuando se lanza una aplicación por primera vez, .NET Framework compila el código CIL en código ejecutable utilizando su compilador justo a tiempo, y almacena en caché el programa ejecutable en la caché de imágenes nativas de .NET. Debido al almacenamiento en caché, la aplicación se inicia más rápidamente en los siguientes lanzamientos, aunque el primer lanzamiento suele ser más lento. Para acelerar el primer lanzamiento, los desarrolladores pueden utilizar la utilidad Native Image Generator para compilar y almacenar en caché manualmente antes de tiempo cualquier aplicación .NET.
El recolector de basura, que está integrado en el entorno, puede introducir retrasos de ejecución imprevistos sobre los que el desarrollador tiene poco control directo. «En aplicaciones de gran tamaño, el número de objetos con los que el recolector de basura debe trabajar puede llegar a ser muy grande, lo que significa que puede tardar mucho tiempo en visitar y reorganizar todos ellos.»
.NET Framework proporciona soporte para llamar a Streaming SIMD Extensions (SSE) a través de código gestionado desde abril de 2014 en Visual Studio 2013 Update 2. Sin embargo, Mono ha proporcionado soporte para las Extensiones SIMD desde la versión 2.2 dentro del espacio de nombres Mono.Simd en 2009. El desarrollador principal de Mono, Miguel de Icaza, ha expresado su esperanza de que este soporte SIMD sea adoptado por el estándar ECMA de CLR. Las extensiones SIMD de flujo han estado disponibles en las CPU x86 desde la introducción del Pentium III. Algunas otras arquitecturas, como ARM y MIPS, también tienen extensiones SIMD. En caso de que la CPU carezca de soporte para esas extensiones, las instrucciones se simulan en software.