Unidad 1

Descargar estos apunte en pdf o html

Índice

Conceptos previos

Introducción a .NET o dotnet

.NET 10 LTS

Conceptos previos

Microprocesador

El microprocesador es el corazón de cualquier dispositivo electrónico, como un ordenador o un teléfono móvil. Se trata de un circuito integrado complejo que, en esencia, funciona como el "cerebro" del sistema, ya que es capaz de ejecutar las instrucciones que componen un programa. Estas instrucciones, conocidas como lenguaje máquina o código máquina, son específicas para cada tipo de microprocesador, lo que significa que un programa escrito para un microprocesador concreto no funcionará en otro diferente.

Para crear programas que un microprocesador pueda entender, los programadores utilizan un lenguaje de programación llamado ensamblador. El ensamblador es un lenguaje de bajo nivel que traduce las instrucciones escritas por el programador a código máquina que el microprocesador puede ejecutar. Cada microprocesador tiene su propio ensamblador específico, adaptado a su conjunto de instrucciones único. Aunque programar en ensamblador puede ser más complejo que utilizar lenguajes de alto nivel, ofrece un control preciso sobre el hardware y permite optimizar el rendimiento del programa.

cluster_arm ARM cluster_x64 x64 ARM Microprocesador ARM ARMv8_A Código máquina ARMv8-A ARMv8_A->ARM Ejecución x64 Microprocesador x64 x86_64 Código máquina x86-64 x86_64->x64 Ejecución

Plataforma

Una plataforma es el entorno de hardware y software sobre el que se ejecuta un programa informático. Incluye el sistema operativo, el microprocesador, las bibliotecas de software y las herramientas de desarrollo necesarias para ejecutar y compilar programas.

Esto significa que aunque dos equipos usen el mismo microprocesador con el mismo conjunto de instrucciones, si ambos equipos usan sistemas operativos diferentes, los programas no serán compatibles ya que el proceso de carga y ejecución de los programas es diferente en cada sistema operativo.

Es por tanto que a partir de ahora nos referiremos a la plataforma a la hora de hablar de programas y no solo del microprocesador.

cluster_x64W x64 + WINDOWS cluster_x64L x64 + LINUX x64W Plataforma x64 + Windows x86_64_WIN Ejecutable Windows x64 x86_64_WIN->x64W Ejecución x64L Plataforma x64 + Linux x86_64LIN Ejecutable Linux x64 x86_64LIN->x64L Ejecución

Lenguajes de alto nivel

Programar directamente en ensamblador, aunque ofrece un control absoluto sobre el microprocesador, resulta una tarea ardua y propensa a errores para los programadores. Su sintaxis críptica y la necesidad de gestionar detalles de bajo nivel dificultan la escritura y comprensión de programas extensos.

Para solventar esta problemática, surgieron los lenguajes de alto nivel. Estos lenguajes, como Python, C o C++, emplean una sintaxis más cercana al lenguaje humano y abstraen gran parte de la complejidad del hardware subyacente. De esta forma, los programadores pueden centrarse en la lógica del programa en lugar de en los detalles de implementación. A la hora de ejecutar un programa escrito en un lenguaje de alto nivel, existen dos enfoques principales: la interpretación, donde un intérprete ejecuta el código directamente instrucción por instrucción, y la compilación, donde un compilador traduce previamente todo el programa a lenguaje máquina para su posterior ejecución, generalmente más rápida.

Interpretación

El interprete ejecuta el código fuente directamente para un plataforma, sin necesidad de una fase previa de traducción a lenguaje máquina. Cada instrucción se analiza y ejecuta en tiempo real, lo que permite una mayor flexibilidad y facilidad de depuración. Sin embargo, esta flexibilidad conlleva una pérdida de rendimiento, ya que el código se interpreta cada vez que se ejecuta, lo que ralentiza la ejecución del programa. Los lenguajes de script, como Python o JavaScript, suelen emplear este enfoque. Además, necesitaremos una implementación del intérprete para cada plataforma donde queramos ejecutar el programa.

Su uso es especialmente interesante cuando vamos a realizar pequeñas tareas o scripts que no requieran un gran rendimiento. Además, es muy útil para aplicaciones web o servidores que necesiten actualizarse constantemente sin interrumpir el servicio.

cluster_compilacion_x64W INTERPRETACIÓN programa_interpretado Script en lenguaje Python interprete_x64W Intérprete x64 + Windows programa_interpretado->interprete_x64W Ejecución interprete_ARMA Intérprete ARM + Android programa_interpretado->interprete_ARMA Ejecución plataforma_x64W Plataforma x64 + Windows interprete_x64W->plataforma_x64W Código máquina plataforma_ARMA Plataforma ARM + Android interprete_ARMA->plataforma_ARMA Código máquina

Compilación

El compilador es una herramienta fundamental en el desarrollo de software, que transforma el código fuente escrito en un lenguaje de alto nivel comprensible para los humanos, un formato que la máquina puede entender y ejecutar. Este proceso involucra un análisis sintáctico del código para verificar su corrección y luego su traducción a un lenguaje ensamblador específico del microprocesador donde se ejecutará el programa. El resultado de esta compilación es un archivo conocido como código objeto, que contiene instrucciones en un formato intermedio.

Sin embargo, este código objeto no es directamente ejecutable. Requiere un paso adicional llamado "enlazado", donde se combina con otras bibliotecas y módulos necesarios para el funcionamiento del programa. El enlazador crea un archivo ejecutable final, que incluye un cargador para que el sistema operativo pueda ubicarlo en memoria y ejecutarlo. Este archivo ejecutable es específico de la plataforma y arquitectura de destino, lo que significa que solo funcionará en sistemas compatibles. Cada modificación en el código fuente implica una nueva compilación para generar un ejecutable actualizado. A pesar de este requisito, la ventaja de la compilación es una ejecución más rápida y eficiente del programa en comparación con otros métodos de traducción.

cluster_compilacion_x64 COMPILACIÓN programa_cpp Programa en lenguaje C++ ensamblador_x64 Ensamblador x64 OBJ programa_cpp->ensamblador_x64 Compilación ensamblador_arm Ensamblador ARM OBJ programa_cpp->ensamblador_arm Compilación plataforma_x64Win Plataforma x64 + Windows plataforma_armLin Plataforma ARM + Linux enlazador_x64Win Enlazador crea cargador Windows con x64 ensamblador_x64->enlazador_x64Win Enlace enlazador_armLin Enlazador crea cargador Linux con ARM ensamblador_arm->enlazador_armLin Enlace enlazador_x64Win->plataforma_x64Win Ejecución enlazador_armLin->plataforma_armLin Ejecución

Ejecución a través de un runtime

En el caso de los lenguajes de alto nivel, como C# o Java, la ejecución de los programas se realiza a través de un entorno de ejecución o runtime. Este entorno proporciona una capa de abstracción entre el código fuente y el hardware subyacente, lo que permite la portabilidad de los programas entre diferentes plataformas. El runtime se encarga de cargar, interpretar y ejecutar el código, así como de gestionar la memoria y los recursos del sistema. Además, proporciona una serie de bibliotecas y servicios que facilitan el desarrollo de aplicaciones, como la gestión de excepciones, la concurrencia o la entrada/salida.

Para ello usarán un bytecode o código intermedio que será interpretado por un JIT (Just In Time) o compilador en tiempo de ejecución que transformará el código intermedio en código máquina para la plataforma concreta.

cluster_ejecucion_jvm EJECUCIÓN EN JAVA VM cluster_plataforma_x64W PLATAFORMA CON WINDOWS cluster_plataforma_armLin PLATAFORMA CON LINUX codigo_fuente_java Código fuente Java bytecode_java Bytecode Java (.class) codigo_fuente_java->bytecode_java Compilación codigo_fuente_scala Código fuente Scala codigo_fuente_scala->bytecode_java Compilación jre_x64W JRE para x64 + Windows bytecode_java->jre_x64W Ejecución Carga (Classloader) jre_armLin JRE para ARM + Linux bytecode_java->jre_armLin Ejecución Carga (Classloader) microprocesador_x64W Microprocesador x64 jre_x64W->microprocesador_x64W Intérprete JIT microprocesador_armLin Microprocesador ARM jre_armLin->microprocesador_armLin Intérprete JIT

Introducción a .NET o dotnet

Un poco de historia

roadmap

Versiones del lenguaje CSharp según la plataforma

Si vamos a la documentación oficial podemos resumir:

Plataforma Versión de C#
.NET Framework 4.8 7.3
.NET Core 3.1 8
... ...
.NET 8.x 12
.NET 10.x 14

Nota

Como pasa en otros lenguajes con historia como por ejemplo Java, Php, C++, etc. tanto la sintaxis del lenguaje como las estructuras del mismo han ido evolucionando a lo largo de las versiones. Aunque a lo largo de los apuntes vamos a tratar de indicar la versión aquellos aspectos sintácticos relevantes. Nosotros nos vamos a centrar en las características más actuales del lenguaje. Sin embargo, es posible que veamos varias formas de hacer un mismo proceso. En este caso iremos indicando la versión de C# en la que se introdujo cada característica.

.NET 10 LTS

Common Language Runtime (CLR)

  • También podemos llamarlo .NET Runtime o Runtime a secas o si quisiéramos explicarlo de forma informal y simplificada con nuestras palabras podríamos decir que ... Runtime = "Software que se encarga de ejecutar algo y por tanto sabe como hacerlo".
  • De una manera más 'formal' podemos decir que el CLR es la capa que hay justo por encima del SO y se encarga de gestionar la ejecución de las aplicaciones en el. Su uso es muy común y existen otros runtime como el equivalente Java™️ denominado JRE (Java™️ Runtime Environment)

CLR_Architecture cluster_0 CLR (Common Language Runtime) bcs Librería de clases base (BCL) ts Manejo de hilos comm Integración Lenguajes Comunes (COM) tc Verificador de tipos em Controlador de excepciones se Motor de seguridad de Motor de depuración il JIT cm Controlador de código gc Recolector Basura (GC) cl Cargador de clases

Common Intermediate Language (CIL)

Ensamblado o Ensamble

cluster_ejecucion_jvm EJECUCIÓN EN .NET cluster_plataforma_x64W PLATAFORMA CON WINDOWS cluster_plataforma_armLin PLATAFORMA CON LINUX codigo_fuente_csharp Código fuente C# cil_dotnet CIL Esamblado (.dll) codigo_fuente_csharp->cil_dotnet Compilación codigo_fuente_fsharp Código fuente F# codigo_fuente_fsharp->cil_dotnet Compilación clr_x64W CLR para x64 + Windows cil_dotnet->clr_x64W Ejecución Carga ensamblado clr_armLin CLR para ARM + Linux cil_dotnet->clr_armLin Ejecución Carga ensamblado microprocesador_x64W Microprocesador x64 clr_x64W->microprocesador_x64W Intérprete JIT microprocesador_armLin Microprocesador ARM clr_armLin->microprocesador_armLin Intérprete JIT

Librerías de clase base BCL

Ejemplo de namespaces en las BCL

Espacio de nombres Uso definiciones que contiene
System Tipos muy frecuentemente usados, como los tipos básicos, tablas, excepciones, fechas, números aleatorios, recolector de basura, entrada/salida en consola, etc.
System.IO Manipulación de ficheros y otros flujos de datos.
System.Collections Colecciones de datos de uso común como pilas, colas, listas, diccionarios, etc.

Sistema Común de Tipos (CTS)

  • Cada lenguaje gestionado puede tener y definir sus propios tipos de datos que pueden ser diferentes.
  • Pero todos ellos deben cumplir unas reglas para que el CLR los acepte a través del CIL generado.

Especificación Común del Lenguaje (CLS)

  • Reglas que tienen que seguir las definiciones de los tipos de un lenguaje gestionado para poder ser accedidos por otro lenguaje gestionado.