<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Baltasar García Perez-Schofield</title>
    <description>The latest articles on DEV Community by Baltasar García Perez-Schofield (@baltasarq).</description>
    <link>https://dev.to/baltasarq</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F156438%2Fc92243a0-0316-41ba-9445-ba8c9ee76d3b.png</url>
      <title>DEV Community: Baltasar García Perez-Schofield</title>
      <link>https://dev.to/baltasarq</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/baltasarq"/>
    <language>en</language>
    <item>
      <title>¿Utilizar IA? El vuelo del "Lady Be Good"</title>
      <dc:creator>Baltasar García Perez-Schofield</dc:creator>
      <pubDate>Thu, 15 Oct 2026 09:13:54 +0000</pubDate>
      <link>https://dev.to/baltasarq/utilizar-ia-el-vuelo-del-lady-be-good-5c63</link>
      <guid>https://dev.to/baltasarq/utilizar-ia-el-vuelo-del-lady-be-good-5c63</guid>
      <description>&lt;p&gt;El otro día, se me ocurrió que utilizar inteligencia artificial para programar, especialmente cuando estás empezando, tiene consecuencias muy similares al (único) vuelo del &lt;em&gt;Lady Be Good&lt;/em&gt;. Al fin y al cabo, todo se reduce a lo que sucede cuando no entiendes lo que estás haciendo.&lt;/p&gt;

&lt;p&gt;El &lt;em&gt;Lady Be Good&lt;/em&gt; fue un bombardero &lt;strong&gt;B-24&lt;/strong&gt; &lt;em&gt;Liberator&lt;/em&gt; que participó en la Segunda Guerra Mundial. Su tripulación estaba compuesta por un grupo bisoño, comandado por el teniente William Hatton. Sí, habían recibido el entrenamiento estándar, sabían pilotar el avión, y conocían, al menos, los rudimentos de la navegación.&lt;/p&gt;

&lt;p&gt;El día 4 de abril de 1943, partieron de la base de Benina, entre Libia y Egipto, con la misión de bombardear Nápoles. No eran el único aparato, por lo que se sentían seguros ante la perspectiva de seguir a los otros 24 bombarderos tripulados por aviadores experimentados. Se crearon dos grupos, el primero despegó normalmente, pero del segundo, al desencadenarse una tormenta de arena, solo pudieron despegar cuatro, entre ellos, nuestro protagonista, aunque con algunos instrumentos dañados.&lt;/p&gt;

&lt;p&gt;Al llegar a Nápoles soltaron sus bombas y regresaron. El &lt;em&gt;Lady Be Good&lt;/em&gt; fue el último en dar la vuelta, y se quedó atrás del disperso grupo, sin contacto visual. Habían pasado más de cinco horas desde el despegue, y se hizo de noche.&lt;/p&gt;

&lt;p&gt;El problema de pilotar de noche es que el desierto puede parecer mar, y el mar puede parecer desierto. Y eso si puedes apreciar algo, puesto que no sería la primera vez que el piloto pierde la conciencia situacional y acaba precipitándose al suelo pensando que está subiendo.&lt;/p&gt;

&lt;p&gt;A las 23:10, todos los aparatos habían aterrizado. Uno de ellos en Malta, por falta de combustible. Todos habían regresado... menos el &lt;em&gt;Lady Be Good&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;A las 00:10, se recibió en una estación de control de tierra una transmisión del &lt;em&gt;Lady Be Good&lt;/em&gt;. Pedía ayuda para orientarse, debido a la inexperiencia de su navegador. La estación de tierra podía decirles en qué rumbo volaban, pero no su posición, ni siquiera si se estaban alejando o acercando. La estación les indicó el rumbo, que era el que estaba siguiendo la nave, por lo que supusieron que fuertes vientos en contra habían ralentizado al aparato.&lt;/p&gt;

&lt;p&gt;No era así. Habían pasado hacía tiempo la base de la que habían despegado, pero la noche les impedía apreciar visualmente que estaban sobre el desierto libio. Y siguieron adentrándose en él.&lt;/p&gt;

&lt;p&gt;Una hora más tarde, habían perdido el contacto por radio, y se dieron cuenta de que estaban al sur de la base, aunque no a cuánta distancia.&lt;/p&gt;

&lt;p&gt;La expedición de rescate, que solo cubrió el extremo sur del mediterráneo y la costa, no encontró nada. Se dió al avión y sus tripulantes como desaparecidos. Cuando los aliados tomaron Nápoles, revisaron los registros de prisioneros, y, al no encontrar sus nombres, asumieron que habían caído al mar y fallecido.&lt;/p&gt;

&lt;p&gt;El problema, sin duda, fue delegar la comprensión y seguimiento de la misión en otros, lo que impidió que ellos mismos fueran conscientes de lo que necesitaban hacer.&lt;/p&gt;

&lt;h2&gt;
  
  
  Vale, pero... ¿qué pasó con el &lt;em&gt;Lady Be Good&lt;/em&gt;?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft982p9suaptenb1vaqkj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ft982p9suaptenb1vaqkj.jpg" alt="Los restos del " width="400" height="160"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Los restos del aparato se encontraron por casualidad, cuando en 1958 una avioneta buscaba a vista de pájaro lugares adecuados para prospección petrolífera. El suceso fue comunicado, y en 1960 el ejército del aire de los Estados Unidos lanzó una expedición de rescate. Lo que descubrieron fue aterrador e increíblemente emocionante, a partes iguales.&lt;/p&gt;

&lt;p&gt;El avión en sí había aterrizado por sí mismo al quedarse sin combustible. Al tomar tierra, se había partido en dos, pero exceptuando ese desperfecto mayor, se encontraron intactos los aparatos del avión, como las ametralladores, y su carga, que incluía varios barriles de agua potable y raciones de comida. Los tripulantes no estaban allí.&lt;/p&gt;

&lt;p&gt;Nos habíamos quedado con los tripulantes dándose cuenta de que sobrevolaban el desierto, en alguna posición al sur de su base, y con el combustible a punto de acabarse.&lt;/p&gt;

&lt;p&gt;Los aviadores saltaron en paracaídas sobre el desierto, consiguiendo reunirse todos ellos... menos uno, que falleció al no desplegarse correctamente su paracaídas. Se encontraban a unos 27 km. al norte de donde finalmente fue a reposar el aparato. Contaban con una cantimplora de agua por persona y unas pequeñas raciones de comida de supervivencia. Su situación era crítica, y eran conscientes de que no les encontrarían.&lt;/p&gt;

&lt;p&gt;Resolvieron comenzar a caminar hacia el norte, sin saber que estaban a más de 500 km. de distancia de la base. Era obvio que no iban a conseguir llegar. Y claro, aquí podríamos empezar a plantearnos preguntas del tipo: ¿y sí...?&lt;/p&gt;

&lt;p&gt;¿Y si se hubieran quedado en el avión, con su suministro de agua potable? ¿Y si hubieran encontrado a su compañero muerto, a aproximadamente un kilómetro al norte, con su botella de agua y raciones intactas? ¿Y si hubieran caminado hacia el sur, hacia el oasis de Wadi Zighen, situado a unos 100 km.? ¿Y si...?&lt;/p&gt;

&lt;p&gt;En realidad, el curso de acción más lógico es el que tomaron. Quedarse en el avión no garantiza sobrevivir, y caminar hacia el sur no tiene sentido si no sabes exactamente dónde estás. Y &lt;a href="https://www.ladybegood.net/maps/index.htm" rel="noopener noreferrer"&gt;la tripulación del &lt;em&gt;Lady Be Good&lt;/em&gt; solo tenía una idea de su situación a muy grandes rasgos&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Aquí es donde empieza la parte épica. Se supone que un humano puede aguantar tres días sin beber. Nuestros protagonistas caminaron casi veinte kilómetros diarios durante más de cinco días con unas botellas de agua y raciones de comida claramente insuficientes. Iban dejando marcadores hechos con los restos de sus paracaídas, pensando que quizás una expedición de rescate pudiese encontrar su avión.&lt;/p&gt;

&lt;p&gt;Al segundo día, encontraron rodadas de camiones que se dirigían hacia el noroeste, lo que supuso una importante inyección de moral. Resolvieron seguirlas. No sabían, claro, que habían sido dejadas más de un año antes.&lt;/p&gt;

&lt;p&gt;Al quinto día de marcha, con todos los recursos agotados, sedientos, hambrientos, y casi ciegos por el resplandor del reflejo del sol en la arena, "solo" pudieron caminar 16 km. La mayoría se queda atrás a esperar una posible ayuda. Tres de ellos (los sargentos Moore, Ripslinger y Shelley), resolvieron continuar caminando. En este punto se habían alejado unos 116 km. del avión, una hazaña épica, aunque desgraciadamente, inútil.&lt;/p&gt;

&lt;p&gt;El grupo "acampado" (cubriéndose con los restos de los paracaídas), con tan solo unas gotas de agua para mojar la lengua, aún sobrevivió tres días más. Al mismo tiempo, el sargento Ripslinger moría a unos 44 km., dejando escrito en su diario que seguían intentando salir del mar de dunas de arena. Al sargento Shelley se le encontró a otros 16 km al noroeste del de Ripslinger, lo que representa unos increíbles 176 km. de caminata en total.&lt;/p&gt;

&lt;p&gt;El cuerpo de Moore nunca fue encontrado oficialmente. Cuando aún se creía que el &lt;a href="https://es.wikipedia.org/wiki/Lady_Be_Good_(B-24)" rel="noopener noreferrer"&gt;&lt;em&gt;Lady Be Good&lt;/em&gt;&lt;/a&gt; se había caído al mar, se encontró un esqueleto por la zona, pero fue enterrado en la arena, y no se investigó más.&lt;/p&gt;

</description>
      <category>spanish</category>
      <category>ai</category>
      <category>war</category>
    </item>
    <item>
      <title>¡Go, Go, Go! ¡Es golang!</title>
      <dc:creator>Baltasar García Perez-Schofield</dc:creator>
      <pubDate>Fri, 09 Oct 2026 08:37:51 +0000</pubDate>
      <link>https://dev.to/baltasarq/go-go-go-oj3</link>
      <guid>https://dev.to/baltasarq/go-go-go-oj3</guid>
      <description>&lt;p&gt;El lenguaje de programación &lt;a href="https://es.wikipedia.org/wiki/Go_(lenguaje_de_programaci%C3%B3n)" rel="noopener noreferrer"&gt;&lt;strong&gt;Go&lt;/strong&gt;&lt;/a&gt; se ha alzado como el dominante entre los lenguajes de programación actuales para servidores. ¿Por qué? Porque genera un ejecutable. Un solo ejecutable. Solo un archivo. La instalación es trivial: solo copia el archivo en el servidor, y se acabó.&lt;/p&gt;

&lt;p&gt;Desde el principio, los creadores de &lt;strong&gt;Go&lt;/strong&gt; se decidieron a solucionar los típicos problemas presentes en C y C++. El primero de todos, era la velocidad de compilación. El segundo ya lo hemos visto: la necesidad de mantener una infraestructura de DLL con las versiones correctas, frente a la decisión tomada de generar un ejecutable estático, es decir, que lo incluye todo, sin dependencias. El tercero, solucionar las ambigüedades presentes en C, además de las posibilidades de dispararte en el pie gracias a C++.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off." &lt;a href="https://www.stroustrup.com/quotes.html" rel="noopener noreferrer"&gt;&lt;em&gt;Bjarne Stroustrup&lt;/em&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;"Con C es fácil dispararte en tu propio pie; C++ lo hace más difícil, pero cuando lo haces, te has volado la pierna entera." &lt;em&gt;Bjarne Stroustrup&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Con &lt;strong&gt;Go&lt;/strong&gt;, no existe un preprocesador. La instrucción &lt;code&gt;import&lt;/code&gt; acepta el nombre de un módulo entre comillas. Por ejemplo, &lt;code&gt;Printf()&lt;/code&gt; está en el módulo &lt;code&gt;fmt&lt;/code&gt;. ¿&lt;code&gt;Printf&lt;/code&gt; con mayúscula? Pues sí, porque los símbolos públicos de un módulo llevan la inicial en mayúscula. Y siempre se antepone el nombre del módulo, separado por un punto del identificador. Las funciones se marcan con la palabra clave &lt;code&gt;func&lt;/code&gt;. No hay &lt;code&gt;void&lt;/code&gt;, simplemente no se pone nada.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello, world!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Las variables locales se marcan con &lt;code&gt;var&lt;/code&gt; (a no ser que su tipo se deduzca de la inicialización, en ese caso se omite &lt;code&gt;var&lt;/code&gt; y se utiliza ':='). Los tipos siempre se colocan a la derecha del identificador... es práctico imaginarse que hay un ':' tras el nombre del identificador.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;distanciaPuntos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;y2&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;distX&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;x1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;x2&lt;/span&gt;
    &lt;span class="n"&gt;distY&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;y1&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;y2&lt;/span&gt;

    &lt;span class="n"&gt;distX&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="n"&gt;distX&lt;/span&gt;
    &lt;span class="n"&gt;distY&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="n"&gt;distY&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;math&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sqrt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;distX&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;distY&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Los tipos de números reales son dos: &lt;code&gt;float32&lt;/code&gt; y &lt;code&gt;float64&lt;/code&gt;. La función &lt;code&gt;Sqrt()&lt;/code&gt; se encuentra en el módulo &lt;code&gt;math&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Y no, no se ponen puntos y coma (';'), a no ser que quieras introducir dos instrucciones en la misma línea. Las llaves de apertura ('{'), siempre se abren en la última posición de la instrucción que genera el bloque de código. El cierre de llave ('}'), siempre va en una línea aparte.&lt;/p&gt;

&lt;p&gt;La palabra &lt;code&gt;package&lt;/code&gt; le da su nombre al módulo; aquel que tiene la función &lt;code&gt;main()&lt;/code&gt; siempre es el módulo &lt;code&gt;main&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;go run hello.go
Hello, world!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y hay que reconocer que impresiona la velocidad de compilación de &lt;strong&gt;Go&lt;/strong&gt;. La apariencia es que el programa se ejecuta inmediatamante. Pero.. ¿qué ha generado?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;go build hello.go
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls
&lt;/span&gt;hello hello.go
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
2424611 oct  9 09:29 hello
     65 oct  9 09:27 hello.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Efectivamente, se trata de un ejecutable estático, o también conocido como &lt;em&gt;fat binary&lt;/em&gt;. Y es que el programa tiene un tamaño de casi 2.5 Mb.&lt;/p&gt;

&lt;p&gt;El programa equivalente en C++ es el ya conocido.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;iostream&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;
&lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;cout&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="s"&gt;"Hello, world!"&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;endl&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generar el ejecutable es una cuestión ya conocida.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;g++ hello.cpp
&lt;span class="nv"&gt;$ &lt;/span&gt;./a.out
Hello, world!
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls
&lt;/span&gt;a.out  hello  hello.cpp  hello.go
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
   16288 oct  9 09:32 a.out
 2424611 oct  9 09:29 hello
      94 oct  9 09:32 hello.cpp
      65 oct  9 09:27 hello.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Parece que no hay color, ¿verdad? El ejecutable de C++ solo ocupa 16 Kb. Pero espera. C++ no genera ejecutables estáticos por defecto, sino que utiliza la DLL de la librería estándar de C++.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt; /usr/lib/libstdc++&lt;span class="k"&gt;*&lt;/span&gt;
     319 ago 10 22:04 /usr/lib/libstdc++.modules.json
      19 ago 10 22:04 /usr/lib/libstdc++.so -&amp;gt; libstdc++.so.6.0.36
      19 ago 10 22:04 /usr/lib/libstdc++.so.6 -&amp;gt; libstdc++.so.6.0.36
 2939928 ago 10 22:04 /usr/lib/libstdc++.so.6.0.36
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;¡Pues casi 3 Mb! Vamos a generar el ejecutable estático, en cualquier caso.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;g++ &lt;span class="nt"&gt;--static&lt;/span&gt; hello.cpp
&lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;ls&lt;/span&gt; &lt;span class="nt"&gt;-l&lt;/span&gt;
total 4836
 2517752 oct  9 09:40 a.out
 2424611 oct  9 09:29 hello
      94 oct  9 09:32 hello.cpp
      65 oct  9 09:27 hello.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ya vemos que no hay mucha diferencia en realidad.&lt;/p&gt;

&lt;p&gt;Pongamos un ejemplo práctico. Un ejercicio estrella es... la sucesión de Fibonacci. Pero vamos a crearlo como lo haríamos con &lt;strong&gt;Python&lt;/strong&gt;, generando un &lt;em&gt;array&lt;/em&gt; (lo más parecido a una lista en &lt;strong&gt;Go&lt;/strong&gt;). Efectivamente, &lt;strong&gt;Go&lt;/strong&gt; permite el manejo de &lt;em&gt;arrays&lt;/em&gt; dinámicos de forma sencilla. Si queremos crear un literal de &lt;em&gt;array&lt;/em&gt;, solo tenemos que utilizar las llaves tras el tipo... ¡los corchetes van a la izquierda! A continuación, vemos un &lt;em&gt;array&lt;/em&gt; con el inicio de la sucesión de Fibonacci. Además, &lt;em&gt;append()&lt;/em&gt; permite añadir un elemento nuevo al &lt;em&gt;array&lt;/em&gt; de forma sencilla.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;uint64&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hay varios tipos predefinidos, varios de ellos son los enteros de diferentes tamaños. &lt;code&gt;int8&lt;/code&gt; es un entero de 8 bits, aceptando valores de -128 a 127. &lt;code&gt;uint8&lt;/code&gt; es un entero sin signo de 8 bits (o 1 byte), y por eso tiene un alias, &lt;code&gt;byte&lt;/code&gt;, ya que acepta valores de 0 a 255. Tenemos enteros, y enteros sin signo, de 16 bits (2 bytes, -32768 a 32767), 32 bits (4 bytes, de -2 mil millones a 2 mil millones aprox.), y 64 bits (8 bytes, una locura). El tipo &lt;code&gt;int&lt;/code&gt; equivale al entero con signo del mismo tamaño que el tamaño de palabra del sistema, típicamente &lt;code&gt;int32&lt;/code&gt;, o &lt;code&gt;int64&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;El tipo escogido es &lt;code&gt;uint64&lt;/code&gt;, pues la sucesión de Fibonacci no tiene negativos, y crece muy rápidamente.&lt;/p&gt;

&lt;p&gt;El bucle &lt;code&gt;for&lt;/code&gt; puede sorprendernos; de hecho es el único bucle disponible, &lt;code&gt;for &amp;lt;condición&amp;gt;&lt;/code&gt; es el bucle &lt;em&gt;while&lt;/em&gt;. El típico bucle &lt;code&gt;for&lt;/code&gt; de &lt;strong&gt;C&lt;/strong&gt; es prácticamente el mismo. Eso sí, al igual que con &lt;code&gt;if&lt;/code&gt;, la condición no va entre paréntesis.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"fmt"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;fibo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="kt"&gt;uint64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;uint64&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;fibo&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;uint64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;uint64&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;lenFibo&lt;/span&gt; &lt;span class="kt"&gt;uint64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;uint64&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fibo&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="n"&gt;lenFibo&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fibo&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="kt"&gt;uint64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;lenFibo&lt;/span&gt;
    &lt;span class="n"&gt;toret&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fibo&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;toret&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;toret&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;toret&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;toret&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;toret&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fibo&lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="kt"&gt;uint64&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Fibo %03d: %v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;fibo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La salida del programa es:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="err"&gt;❯&lt;/span&gt; &lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="n"&gt;fibo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt;
&lt;span class="n"&gt;Fibo&lt;/span&gt;

&lt;span class="n"&gt;Fibo&lt;/span&gt; &lt;span class="m"&gt;000&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;Fibo&lt;/span&gt; &lt;span class="m"&gt;001&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Fibo&lt;/span&gt; &lt;span class="m"&gt;002&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Fibo&lt;/span&gt; &lt;span class="m"&gt;003&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Fibo&lt;/span&gt; &lt;span class="m"&gt;004&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Fibo&lt;/span&gt; &lt;span class="m"&gt;005&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Fibo&lt;/span&gt; &lt;span class="m"&gt;006&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Fibo&lt;/span&gt; &lt;span class="m"&gt;007&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;13&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Fibo&lt;/span&gt; &lt;span class="m"&gt;008&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;13&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Fibo&lt;/span&gt; &lt;span class="m"&gt;009&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;13&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt; &lt;span class="m"&gt;34&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Fibo&lt;/span&gt; &lt;span class="m"&gt;010&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;13&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt; &lt;span class="m"&gt;34&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Fibo&lt;/span&gt; &lt;span class="m"&gt;011&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;13&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt; &lt;span class="m"&gt;34&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt; &lt;span class="m"&gt;89&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Fibo&lt;/span&gt; &lt;span class="m"&gt;012&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;13&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt; &lt;span class="m"&gt;34&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt; &lt;span class="m"&gt;89&lt;/span&gt; &lt;span class="m"&gt;144&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Fibo&lt;/span&gt; &lt;span class="m"&gt;013&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;13&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt; &lt;span class="m"&gt;34&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt; &lt;span class="m"&gt;89&lt;/span&gt; &lt;span class="m"&gt;144&lt;/span&gt; &lt;span class="m"&gt;233&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Fibo&lt;/span&gt; &lt;span class="m"&gt;014&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;13&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt; &lt;span class="m"&gt;34&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt; &lt;span class="m"&gt;89&lt;/span&gt; &lt;span class="m"&gt;144&lt;/span&gt; &lt;span class="m"&gt;233&lt;/span&gt; &lt;span class="m"&gt;377&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Fibo&lt;/span&gt; &lt;span class="m"&gt;015&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;13&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt; &lt;span class="m"&gt;34&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt; &lt;span class="m"&gt;89&lt;/span&gt; &lt;span class="m"&gt;144&lt;/span&gt; &lt;span class="m"&gt;233&lt;/span&gt; &lt;span class="m"&gt;377&lt;/span&gt; &lt;span class="m"&gt;610&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Fibo&lt;/span&gt; &lt;span class="m"&gt;016&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;13&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt; &lt;span class="m"&gt;34&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt; &lt;span class="m"&gt;89&lt;/span&gt; &lt;span class="m"&gt;144&lt;/span&gt; &lt;span class="m"&gt;233&lt;/span&gt; &lt;span class="m"&gt;377&lt;/span&gt; &lt;span class="m"&gt;610&lt;/span&gt; &lt;span class="m"&gt;987&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Fibo&lt;/span&gt; &lt;span class="m"&gt;017&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;13&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt; &lt;span class="m"&gt;34&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt; &lt;span class="m"&gt;89&lt;/span&gt; &lt;span class="m"&gt;144&lt;/span&gt; &lt;span class="m"&gt;233&lt;/span&gt; &lt;span class="m"&gt;377&lt;/span&gt; &lt;span class="m"&gt;610&lt;/span&gt; &lt;span class="m"&gt;987&lt;/span&gt; &lt;span class="m"&gt;1597&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Fibo&lt;/span&gt; &lt;span class="m"&gt;018&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;13&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt; &lt;span class="m"&gt;34&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt; &lt;span class="m"&gt;89&lt;/span&gt; &lt;span class="m"&gt;144&lt;/span&gt; &lt;span class="m"&gt;233&lt;/span&gt; &lt;span class="m"&gt;377&lt;/span&gt; &lt;span class="m"&gt;610&lt;/span&gt; &lt;span class="m"&gt;987&lt;/span&gt; &lt;span class="m"&gt;1597&lt;/span&gt; &lt;span class="m"&gt;2584&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Fibo&lt;/span&gt; &lt;span class="m"&gt;019&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;13&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt; &lt;span class="m"&gt;34&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt; &lt;span class="m"&gt;89&lt;/span&gt; &lt;span class="m"&gt;144&lt;/span&gt; &lt;span class="m"&gt;233&lt;/span&gt; &lt;span class="m"&gt;377&lt;/span&gt; &lt;span class="m"&gt;610&lt;/span&gt; &lt;span class="m"&gt;987&lt;/span&gt; &lt;span class="m"&gt;1597&lt;/span&gt; &lt;span class="m"&gt;2584&lt;/span&gt; &lt;span class="m"&gt;4181&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;Fibo&lt;/span&gt; &lt;span class="m"&gt;020&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="m"&gt;8&lt;/span&gt; &lt;span class="m"&gt;13&lt;/span&gt; &lt;span class="m"&gt;21&lt;/span&gt; &lt;span class="m"&gt;34&lt;/span&gt; &lt;span class="m"&gt;55&lt;/span&gt; &lt;span class="m"&gt;89&lt;/span&gt; &lt;span class="m"&gt;144&lt;/span&gt; &lt;span class="m"&gt;233&lt;/span&gt; &lt;span class="m"&gt;377&lt;/span&gt; &lt;span class="m"&gt;610&lt;/span&gt; &lt;span class="m"&gt;987&lt;/span&gt; &lt;span class="m"&gt;1597&lt;/span&gt; &lt;span class="m"&gt;2584&lt;/span&gt; &lt;span class="m"&gt;4181&lt;/span&gt; &lt;span class="m"&gt;6765&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La idea con la que me quedo de &lt;strong&gt;Go&lt;/strong&gt; es que es... muy práctico. Esto es normal, debido al interés de sus diseñadores en resolver problemas con los que se enfrentaban todos los días. Concretamente, estaban hartos de tener que esperar y esperar incluso más de 15 minutos para que sus programas compilasen. Y de hecho, fue en esas esperas cuando empezaron a diseñar &lt;strong&gt;Go&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;El uso de módulos por un lado, y estructuras con interfaces por el otro, permite un cierto tipo de programación orientada a objetos, aunque se construya de una manera mucho más primitiva. Pero eso ya lo veremos en la siguiente entrega.&lt;/p&gt;

</description>
      <category>go</category>
      <category>spanish</category>
      <category>programming</category>
      <category>learn</category>
    </item>
    <item>
      <title>Cosas que no sabías que no sabías: los decimales y tú.</title>
      <dc:creator>Baltasar García Perez-Schofield</dc:creator>
      <pubDate>Wed, 07 Oct 2026 15:05:19 +0000</pubDate>
      <link>https://dev.to/baltasarq/cosas-que-no-sabias-que-no-sabias-los-decimales-y-tu-441o</link>
      <guid>https://dev.to/baltasarq/cosas-que-no-sabias-que-no-sabias-los-decimales-y-tu-441o</guid>
      <description>&lt;p&gt;Ya escribí sobre esto anteriormente, en concreto, decía en &lt;a href="https://dev.to/baltasarq/donde-esta-mi-dinero-2j9c"&gt;¿Dónde está mi dinero?&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;La razón tiene que ver con el estándar IEEE 754. Este estándar se publicó en 1985 (aunque se ha desarrollado y revisado a partir de esa fecha). Los números reales son un problema al fin y al cabo. Los números posibles entre 0.1 y 0.2 y entre 0.01 y 0.02 son los mismos: infinitos. En una representación digital, el infinito es una imposibilidad.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Efectivamente, un soporte digital tiene problemas para representar todo aquello que esté relacionado con el infinito. Igual que un círculo, que tiene infinitos lados. ¿Te has dado cuenta de cómo en los videojuegos, nada llega a ser verdaderamente redondo?&lt;/p&gt;

&lt;p&gt;Es fascinante. ¿Podemos llegar a solventar, de verdad, este problema?&lt;/p&gt;

&lt;p&gt;Es una pregunta interesante. Ya sabemos que la respuesta es no, aunque hay varias formas de paliarlo. Al fin y al cabo, si un sistema, aunque utilice un soporte digital, tiene la suficiente precisión, es posible que sea indistinguible para el ser humano.&lt;/p&gt;

&lt;p&gt;Efectivamente, C# tiene soporte para números con decimales que mantienen un buen soporte de precisión. Se trata del &lt;a href="https://learn.microsoft.com/es-es/dotnet/csharp/language-reference/builtin-types/floating-point-numeric-types" rel="noopener noreferrer"&gt;tipo &lt;code&gt;decimal&lt;/code&gt;&lt;/a&gt;. Utilizando este tipo, se emplean muchos más bits para representar la mantisa, y solo unos pocos para representar el exponente.&lt;/p&gt;

&lt;p&gt;Evidentemente esto ayuda, pero no es una solución definitiva. Por ejemplo, en el siguiente programa en Python:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;   
    &lt;span class="nf"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
    &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
        &lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;ERROR &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; != &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;

    &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="mf"&gt;0.1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;...avanzamos hasta que &lt;code&gt;i&lt;/code&gt; es divisible por 10 (es decir, cada 10 elementos), y comprobamos si el resto de la división de &lt;code&gt;x&lt;/code&gt; con 10 es 0. Si esto no se cumple, hemos encontrado una imprecisión. ¿Será un número muy elevado? ¡Solo estamos empleando incrementos de 0.1!&lt;/p&gt;

&lt;p&gt;Pues el resultado es sorprendente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ python precision.py
ERROR 10 != 0.9999999999999999
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ya arrastramos un error significativo después de... ¡tan solo 10 incrementos de 0.1 en 0.1!&lt;/p&gt;

&lt;p&gt;Esto me hizo pensar... ¿era todo distinto en los tiempos del &lt;a href="https://en.wikipedia.org/wiki/ZX_Spectrum" rel="noopener noreferrer"&gt;&lt;code&gt;Speccy&lt;/code&gt;&lt;/a&gt;? Pues resulta que... no.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10 let x = 0
20 for i = 0 to 100
30     print x: pause 0
40     let x = x + 0.1
50 next i
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La salida es... ¿la esperada?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1
1.1
1.2
1.3
1.4
...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffx48izvrpgwjitsr884t.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ffx48izvrpgwjitsr884t.jpg" alt="Sumando de 0.1 en 0.1" width="649" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Al encontrarme con esto, me puse a buscar las razones que pudieran explicar este comportamiento. Resulta que Sinclair Basic almacena las variables numéricas en 5 bytes, sin importar demasiado si son enteras o decimales. Si son enteras, los bits dedicados al exponente estarán vacíos, aspecto del que se aprovechan varias rutinas matemáticas en ROM. En cualquier caso, los números en Sinclair Basic no se "desbordan", sino que pasan a representarse como números en coma flotante.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10 let x = 1
20 for i = 0 to 100
30     print x: pause 0
40     let x = x * 100
50 next i
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Por ejemplo, ante un programa como el anterior, la salida pasa a coma flotante a partir de un cierto valor, hasta que admite que no puede representar valores tan grandes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F26pk5qxx8pws98zlgg0j.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F26pk5qxx8pws98zlgg0j.jpg" alt="Números muy grandes en el Speccy" width="647" height="511"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Esto es sencillo de conseguir en el Speccy, porque los números decimales y los números enteros comparten representación: 5 bytes con 0 como byte para el exponente, y un valor en el exponente en caso contrario. Nótese que &lt;code&gt;10 e+38&lt;/code&gt; no deja de ser un número muy grande... ¡un &lt;code&gt;1&lt;/code&gt; seguido de 38 ceros!&lt;/p&gt;

&lt;p&gt;Pero volvamos al PC moderno... ¿podemos conseguir representar estos valores monetarios de forma exacta? Claro que podemos. Ya vimos que la trampa siempre proviene de varias operaciones matemáticas acumuladas. En el artículo enlazado, se guardaba el valor monetario como número entero multiplicado por cien y solo cuando se pedía se dividía entre cien.&lt;/p&gt;

&lt;p&gt;También podemos guardar valor entero y céntimos en una estructura, como se puede ver a continuación.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="nc"&gt;Money&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Value&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;init&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="kt"&gt;byte&lt;/span&gt; &lt;span class="n"&gt;Cents&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;init&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;override&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;ToString&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;,&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cents&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="m"&gt;00&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;explicit&lt;/span&gt; &lt;span class="k"&gt;operator&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Money&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;decimal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;explicit&lt;/span&gt; &lt;span class="k"&gt;operator&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Money&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;decimal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;decimal&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cents&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;explicit&lt;/span&gt; &lt;span class="k"&gt;operator&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Money&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;toret&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cents&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;toret&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;toret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Money&lt;/span&gt; &lt;span class="nf"&gt;From&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Money&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Cents&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Money&lt;/span&gt; &lt;span class="nf"&gt;From&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Money&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;=(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;Cents&lt;/span&gt;&lt;span class="p"&gt;=(&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="p"&gt;)};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Money&lt;/span&gt; &lt;span class="nf"&gt;From&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Money&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;=(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                    &lt;span class="n"&gt;Cents&lt;/span&gt;&lt;span class="p"&gt;=(&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;%&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="p"&gt;)};&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;    
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Los lenguajes de programación intentan hacer el manejo de los datos numéricos tan intuitivo, que a veces nos olvidamos cómo se está representando realmente "por debajo".&lt;/p&gt;

</description>
      <category>programming</category>
      <category>spanish</category>
      <category>sinclair</category>
      <category>float</category>
    </item>
    <item>
      <title>C# ¿Qué me he perdido?</title>
      <dc:creator>Baltasar García Perez-Schofield</dc:creator>
      <pubDate>Fri, 25 Sep 2026 18:25:23 +0000</pubDate>
      <link>https://dev.to/baltasarq/c-que-me-he-perdido-lf7</link>
      <guid>https://dev.to/baltasarq/c-que-me-he-perdido-lf7</guid>
      <description>&lt;p&gt;&lt;a href="https://dotnet.microsoft.com/" rel="noopener noreferrer"&gt;C#&lt;/a&gt; es un lenguaje en constante evolución. Empiezan a escucharse voces que demandan un periodo de estabilidad ante tanto cambio, pero está claro que la última palabra la tiene Microsoft.&lt;/p&gt;

&lt;p&gt;Con la versión 11 de .NET a punto de caramelo, podemos relacionar los últimos cambios más reseñables a C#. Los mejores cambios son los que no se ven: los ingenieros de Microsoft están optimizando agresivamente el código generado por el compilador, de manera que sea tan rápido como sea posible.&lt;/p&gt;

&lt;p&gt;Para la mayor parte del código aquí, necesitamos instalar la .NET 11.0-rc1, configurar el proyecto para usarla, y activar &lt;em&gt;preview&lt;/em&gt;. Un ejemplo de proyecto aparece a continuación.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;Project&lt;/span&gt; &lt;span class="na"&gt;Sdk=&lt;/span&gt;&lt;span class="s"&gt;"Microsoft.NET.Sdk"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

  &lt;span class="nt"&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;OutputType&amp;gt;&lt;/span&gt;Exe&lt;span class="nt"&gt;&amp;lt;/OutputType&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;TargetFramework&amp;gt;&lt;/span&gt;net11.0&lt;span class="nt"&gt;&amp;lt;/TargetFramework&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;RootNamespace&amp;gt;&lt;/span&gt;Matrix&lt;span class="nt"&gt;&amp;lt;/RootNamespace&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ImplicitUsings&amp;gt;&lt;/span&gt;enable&lt;span class="nt"&gt;&amp;lt;/ImplicitUsings&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Nullable&amp;gt;&lt;/span&gt;enable&lt;span class="nt"&gt;&amp;lt;/Nullable&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Preview&amp;gt;&lt;/span&gt;enable&lt;span class="nt"&gt;&amp;lt;/Preview&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;/Project&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vale, pero... ¿cuál es la versión de C# que se corresponde con estas versiones de .NET? Es una buena pregunta, porque no hay una respuesta sencilla. Es imposible, de hecho, obtenerla, mediante la herramienta &lt;code&gt;dotnet&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;.NET&lt;/th&gt;
&lt;th&gt;.NET  9&lt;/th&gt;
&lt;th&gt;.NET 10&lt;/th&gt;
&lt;th&gt;.NET 11&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;C#&lt;/td&gt;
&lt;td&gt;C# 13&lt;/td&gt;
&lt;td&gt;C# 14&lt;/td&gt;
&lt;td&gt;C# 15&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Así que, como decía &lt;a href="https://es.wikipedia.org/wiki/Jack_el_Destripador" rel="noopener noreferrer"&gt;Jacobo, vamos por partes&lt;/a&gt;.&lt;/p&gt;

&lt;h1&gt;
  
  
  Novedades en C
&lt;/h1&gt;

&lt;h2&gt;
  
  
  C# 13: índices negativos
&lt;/h2&gt;

&lt;p&gt;Ahora es posible acceder a elementos desde un índice negativo. Este índice negativo se cuenta desde el último elemento, de manera que -1 se corresponde con el último, -2 el antepenúltimo, etc. Solo es necesario tener en cuenta que, en lugar de utilizar, por ejemplo, -1, la sintaxis exige utilizar ^1.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[^&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;11&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[^&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;12&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[^&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;13&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[^&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;14&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[^&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;15&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[^&lt;/span&gt;&lt;span class="m"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[^&lt;/span&gt;&lt;span class="m"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;17&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[^&lt;/span&gt;&lt;span class="m"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;18&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[^&lt;/span&gt;&lt;span class="m"&gt;9&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;19&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;[^&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;buffer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La salida es la que esperamos:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;20
19
18
17
16
15
14
13
12
11
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  C# 14: La palabra clave field
&lt;/h2&gt;

&lt;p&gt;Ya &lt;a href="https://dev.to/baltasarq/c-get-set-field-getdotnet9--2d3p"&gt;escribí sobre &lt;code&gt;field&lt;/code&gt;en C# recientemente&lt;/a&gt;. De la misma forma en la que disponemos de &lt;code&gt;value&lt;/code&gt;, para representar el valor asignado en la propiedad &lt;code&gt;set&lt;/code&gt;, tenemos ahora &lt;code&gt;field&lt;/code&gt; para representar al atributo sintético.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Punto&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"value &amp;lt; 0"&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;?&lt;/span&gt;&lt;span class="n"&gt;X&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}}&lt;/span&gt;
    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En el código de arriba, comprobamos si el valor que va a ser asignado en el &lt;code&gt;set&lt;/code&gt; (llamado &lt;code&gt;value&lt;/code&gt;), de la propiedad &lt;strong&gt;X&lt;/strong&gt; es o no negativo. En caso de ser negativo, se lanza una excepción. El código es erróneo porque se nombra &lt;code&gt;?x?&lt;/code&gt;para representar el campo a asignar. En este punto, tendríamos que crear un atributo real a la clase.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Punto&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"value &amp;lt; 0"&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}}&lt;/span&gt;

    &lt;span class="c1"&gt;// ...&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;¡Pero ahora ya no es necesario! Volviendo al código de más arriba, podemos escribir lo siguiente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Punto&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;X&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ArgumentException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"value &amp;lt; 0"&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}}&lt;/span&gt;

    &lt;span class="c1"&gt;// ...&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  C# 14: Asignación condicional
&lt;/h2&gt;

&lt;p&gt;Hasta ahora, era posible utilizar el operador &lt;code&gt;?&lt;/code&gt; como parte de una expresión. En caso de que la referencia a la izquierda de &lt;code&gt;?&lt;/code&gt; sea &lt;code&gt;null&lt;/code&gt;, entonces se devuelve directamente &lt;code&gt;null&lt;/code&gt;. En otro caso, se devuelve el resultado de la expresión como tal.&lt;/p&gt;

&lt;p&gt;Por ejemplo, &lt;code&gt;person?.Name&lt;/code&gt; devuelve el nombre del objeto de la clase &lt;strong&gt;Person&lt;/strong&gt; referenciada por &lt;code&gt;person&lt;/code&gt;. Si en cambio, &lt;code&gt;person&lt;/code&gt; es &lt;code&gt;null&lt;/code&gt;, entonces se devuelve &lt;code&gt;null&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Pero es que ahora, además, es posible utilizarla para asignar (o no), un valor, si la referencia a la izquierda de &lt;code&gt;?&lt;/code&gt; no es &lt;code&gt;null&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// ...&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;person&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;people&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FirstOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;age&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;18&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;           &lt;span class="c1"&gt;// Already supported&lt;/span&gt;
&lt;span class="n"&gt;person&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"The One"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;                    &lt;span class="c1"&gt;// New!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  C# 15: Jerarquías cerradas
&lt;/h2&gt;

&lt;p&gt;Es posible crear una jerarquía que se sabe que, en el momento de la compilación, va a tener un número determinado de clases derivadas.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;closed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;init&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Employee&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;Salary&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;init&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Retired&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;Pension&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;init&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En la clase &lt;strong&gt;Person&lt;/strong&gt; añadimos el modificador &lt;code&gt;closed&lt;/code&gt; para indicar que esta clase solo va a tener las clases derivadas que indiquemos; ninguna más.&lt;/p&gt;

&lt;p&gt;Esto permite hacer un tipo de &lt;code&gt;switch&lt;/code&gt; que se base en los tipos derivados de los objetos &lt;strong&gt;Person&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;closed&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Person&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;required&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;init&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;IncomeLabel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Person&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="k"&gt;switch&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;Employee&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Salary"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;Retired&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;"Pension"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;La ventaja es que en este &lt;code&gt;switch&lt;/code&gt; el compilador puede comprobar que hemos tratado todos los posibles casos como clases derivadas tiene &lt;strong&gt;Persona&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;A mi se me ocurre que es una versión super-vitaminada de enumerados, pero claro, con un cierto coste, pues involucra la creación de objetos.&lt;/p&gt;

&lt;h2&gt;
  
  
  C# 15: Uniones
&lt;/h2&gt;

&lt;p&gt;Ya escribí sobre cómo C# soporta &lt;a href="https://dev.to/baltasarq/unionc-f-3jaf"&gt;uniones en C#&lt;/a&gt;, aunque no nos quede demasiado claro para qué exactamente.&lt;/p&gt;

&lt;h2&gt;
  
  
  C# 15: break y continue etiquetados
&lt;/h2&gt;

&lt;p&gt;Esta característica está soportada en Java desde el primer día, pero por algún motivo no ha conseguido llegar hasta C# hasta ahora.&lt;/p&gt;

&lt;p&gt;La idea es la posibilidad de romper un bucle (o saltar una vuelta de bucle), desde un bucle anidado en el primero.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Matrix&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;rnd&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Random&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Fill&lt;/span&gt;
&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rows&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cols&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;++&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rnd&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;Find&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rows&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;++&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cols&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;++&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;j&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;50&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;$"Encontrado en (&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;j&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)"&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;break&lt;/span&gt; &lt;span class="n"&gt;Find&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Matrix&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Matrix&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Rows&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Cols&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;cols&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Rows&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;Cols&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[,]&lt;/span&gt; &lt;span class="n"&gt;Data&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[,])&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Clone&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="nf"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;[,]&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;En el código anterior vemos una clase &lt;strong&gt;Matrix&lt;/strong&gt;, que primero se rellena mediante un doble bucle con valores aleatorios, y después se recorre, de nuevo con un doble-bucle, para buscar el valor 50. En caso de encontrarse, no es suficiente con &lt;code&gt;break&lt;/code&gt;, puesto que solo romperíamos el bucle anidado. Pero con la versión de &lt;code&gt;break&lt;/code&gt; etiquetada, podemos indicar cuál de los dos bucles queremos romper.&lt;/p&gt;

&lt;p&gt;¿Y tú, cómo llevas tanto cambio y tanto avance en C#?&lt;/p&gt;

</description>
      <category>spanish</category>
      <category>csharp</category>
      <category>programming</category>
    </item>
    <item>
      <title>Cosas que no sabías que no sabías: tamaño de un struct</title>
      <dc:creator>Baltasar García Perez-Schofield</dc:creator>
      <pubDate>Thu, 17 Sep 2026 11:56:42 +0000</pubDate>
      <link>https://dev.to/baltasarq/cosas-que-no-sabias-que-no-sabias-tamano-de-un-struct-57kl</link>
      <guid>https://dev.to/baltasarq/cosas-que-no-sabias-que-no-sabias-tamano-de-un-struct-57kl</guid>
      <description>&lt;p&gt;Esta es la primera entrega de una serie en la que exploraremos cuestiones que se "escapan" del alto nivel de los lenguajes de programación hacia el &lt;strong&gt;hardware&lt;/strong&gt; por debajo de nosotros.&lt;/p&gt;

&lt;p&gt;¿Cuánto ocupa una &lt;code&gt;struct&lt;/code&gt;, un registro? Pues... depende. Veamos a continuación un ejemplo en C.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;    &lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;_Deportista&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;total_seconds&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;finished&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;Deportista&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vale, un registro que identifica a un deportista con un número, un tiempo (en segundos), y un booleano que determina si terminó la carrera o no.&lt;/p&gt;

&lt;p&gt;¿Cuál es el tamaño de este registro? De nuevo... depende. Podemos especificar un poco más:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ancho de palabra del ordenador.&lt;/li&gt;
&lt;li&gt;Compilador utilizado.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;El ancho de palabra del ordenador nos permite saber dos cosas: primero, cuántos bytes ocupará un &lt;code&gt;unsigned int&lt;/code&gt;, un entero sin signo. En lenguajes de programación cercanos al hardware, es muy común que el tipo &lt;code&gt;int&lt;/code&gt; coincida con el ancho de palabra de la máquina. Si nuestro ordenador es de 32 bits, es decir, 4 bytes, el tamaño en memoria de un &lt;code&gt;int&lt;/code&gt; será también de 4 bytes. Si nuestra máquina es de 64 bits, es decir, 8 bytes, el tamaño de un &lt;code&gt;int&lt;/code&gt; será... bueno, pues depende del compilador. Puede optar por soportar enteros de 64 o 32 bits, aunque el puntero siempre sea de 64 bits. Por ejemplo, &lt;a href="https://es.wikipedia.org/wiki/64_bits#Modelos_de_datos_de_64_bits" rel="noopener noreferrer"&gt;&lt;code&gt;gcc&lt;/code&gt; y la mayoría de compiladores para x64 optan por seguir utilizando 4 bytes para los enteros&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Si asumimos una máquina de 32 bits, entonces tenemos 4 + 4 + 1, es decir, 9 bytes ocupados por el registro. Si asumimos una máquina de 64 bits, que utilice 32 bits para los enteros, tendremos el mismo resultado. Si asumimos una máquina x64 que utilice 8 bytes para los enteros, tendremos 8 + 8 + 1, es decir, 17 bytes. ¿No?&lt;/p&gt;

&lt;p&gt;Pues lo más probable (y razonable), es que no sea así. El compilador tratará de optimizar el tamaño del registro para soportar el acceso a memoria en palabras, y con una alineación correcta.&lt;/p&gt;

&lt;p&gt;Las siguientes asunciones y descripciones de funcionamiento se hacen todas eligiendo simplificar.&lt;/p&gt;

&lt;p&gt;El bus de datos del ordenador lee o escribe de la memoria siempre con el mismo tamaño mínimo: el ancho de palabra de la arquitectura. Una máquina de 32 bits siempre lee o escribe de 32 en 32 bits, es decir, 4 bytes. Si por poner un ejemplo, lo que queremos son los 2 bytes intermedios, le aplicará posteriormente la máscara &lt;code&gt;0x00FFFF00&lt;/code&gt; para obtener el resultado que le hemos pedido. Este es el acceso a memoria de palabra en palabra.&lt;/p&gt;

&lt;p&gt;En nuestra estructura, los dos primeros miembros están alineados. Son dos accesos, uno por palabra. Supongamos por un momento la misma máquina de 32 bits, que el compilador reserva el tamaño de la estructura exacta, es decir, 9 bytes, y que tenemos un vector de dos deportistas, el número 1, que tardó 10 segundos, y el número 2, que tardó 9. Leemos el primer miembro del primer registro, y obtenemos &lt;code&gt;0x01000000&lt;/code&gt;, para leer el segundo miembro del primer registro, obteniendo &lt;code&gt;0x0A000000&lt;/code&gt;. Ahora leemos el tercer miembro, que es un booleano que ocupa 1 bytes, con el valor 1. Esto sería &lt;code&gt;0x01&lt;/code&gt;. Pero el ordenador no lee de byte en byte, sino de palabra en palabra. Así que lee &lt;code&gt;0x01020000&lt;/code&gt;. Esto es el byte de haber terminado la carrera del primer deportista, más los tres primeros bytes del número del segundo deportista. El ordenador aplica la máscara &lt;code&gt;0xFF000000&lt;/code&gt;, y nos devuelve &lt;code&gt;0x01&lt;/code&gt;. Ahora leemos al segundo miembro. Es la misma palabra de antes, &lt;code&gt;0x01020000&lt;/code&gt;, pero ahora aplicando la máscara &lt;code&gt;0x00FFFFFF&lt;/code&gt;. Pero esto no llega, nos falta un byte por leer, así que leemos la siguiente palabra y le aplicams la máscara &lt;code&gt;0xFF000000&lt;/code&gt;. Tendremos que desplazar los bits del primer valor hacia la izquierda, desplazar los bits del segundo valor hacia la derecha, y hacer un OR. ¡Cada miembro del segundo deportista implica lectura de dos palabras, desplazamientos de bits en los registros y sumas! Esto es así porque el registro no está alineado en memoria.&lt;/p&gt;

&lt;p&gt;Ahora supongamos que el registro no ocupa 9 bytes (4 + 4 + 1), sino 12 bytes (4 + 4 + 4). Es decir, "malgastamos" 4 bytes en el booleano, solo para que el registro esté alineado en memoria. Así, la lectura de cada deportista se puede hacer mediante tres accesos simples a memoria, aunque los tres últimos bytes en realidad no se empleen, y estén siempre a cero. Lo que permite este "desperdicio" es que la velocidad se incremente enormemente. A este desperdicio se le denomina &lt;a href="https://learn.microsoft.com/es-es/cpp/c-language/storage-and-alignment-of-structures?view=msvc-170" rel="noopener noreferrer"&gt;&lt;strong&gt;padding&lt;/strong&gt;&lt;/a&gt;. Y el &lt;strong&gt;padding&lt;/strong&gt; exacto depende de cada compilador, no está estandarizado.&lt;/p&gt;

&lt;p&gt;El primer deportista se lee mediante dos accesos simples a memoria. El booleano se obtiene mediante un acceso simple y un enmascaramiento de &lt;code&gt;0xFF000000&lt;/code&gt;. El segundo deportista se lee mediante dos accesos simples a memoria, pues ya no hay desalineación, más un acceso simple  con un enmascaramiento y así sucesivamente.&lt;/p&gt;

&lt;p&gt;¡Ya sé! Puedo hacer esto:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;    &lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;_Deportista&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;total_seconds&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;finished&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;Deportista&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Le estamos diciendo que utilice un solo bit para almacenar el booleano. Genial, pero nada ha cambiado en realidad. Solo la operación de máscara. Si cambiara algo, volveríamos al problema de la  desalineación en memoria.&lt;/p&gt;

&lt;p&gt;Lo que sí podemos hacer es codificar con el acceso a memoria, y la alineación, en la cabeza. Por ejemplo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;    &lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;_Deportista&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;finished&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;total_seconds&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;short&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;num_penalties&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;Deportista&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esta estructura ocupa 4 + 4 + 4 + 4 = 16 bytes, a pesar de que en principio el campo &lt;strong&gt;finished&lt;/strong&gt; solo ocupa 1 byte, y también que con el número de penalizaciones &lt;strong&gt;num_penalties&lt;/strong&gt;, escogido como un entero corto sin signo, en nuestra arquitectura imaginaria es de solo 16 bits. Pero que por cuestiones de alineación en realidad, no conseguimos ahorrar nada; el compilador creará &lt;strong&gt;padding&lt;/strong&gt; tras &lt;strong&gt;finished&lt;/strong&gt; y tras &lt;strong&gt;num_penalties&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;La cosa cambia si reordenamos los miembros de la estructura:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;    &lt;span class="k"&gt;typedef&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;_Deportista&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;finished&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;short&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;num_penalties&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;total_seconds&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="n"&gt;Deportista&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora, siguiendo los cálculos realizados anteriormente, nuestra estructura ocupa 4 + 4 + 4, es decir, 12 bytes. El compilador solo introducirá un byte de &lt;strong&gt;padding&lt;/strong&gt; tras &lt;strong&gt;num_penalites&lt;/strong&gt;. Tras el segundo acceso a memoria, &lt;strong&gt;finished&lt;/strong&gt; se servirá aplicando la máscara &lt;code&gt;0xFF000000&lt;/code&gt; al valor obtenido, mientras que &lt;strong&gt;num_penalites&lt;/strong&gt; se obtendrá del mismo valor aplicando la máscara &lt;code&gt;0x00FFFF00&lt;/code&gt;.&lt;/p&gt;

</description>
      <category>spanish</category>
      <category>programming</category>
      <category>development</category>
      <category>c</category>
    </item>
    <item>
      <title>Caso de éxito de ingeniería del software: los toolkits gráficos</title>
      <dc:creator>Baltasar García Perez-Schofield</dc:creator>
      <pubDate>Thu, 10 Sep 2026 08:51:33 +0000</pubDate>
      <link>https://dev.to/baltasarq/caso-de-exito-los-toolkits-graficos-4pg8</link>
      <guid>https://dev.to/baltasarq/caso-de-exito-los-toolkits-graficos-4pg8</guid>
      <description>&lt;p&gt;Decíamos en la anterior entrega de esta serie, que un caso que se suele dar a conocer como de éxito es el de los &lt;strong&gt;toolkits&lt;/strong&gt; gráficos. En parte es cierto, hay muchas aplicaciones que utilizan este tipo de módulos. Pero claro, en realidad encierra lo que yo entiendo es un fracaso: solo se puede considerar que aquellas aplicaciones que utilicen ese &lt;strong&gt;toolkit&lt;/strong&gt; específico están construidas sobre esos módulos.&lt;/p&gt;

&lt;p&gt;Es decir, hay muchas aplicaciones que están construidas sobre, por ejemplo, &lt;a href="https://learn.microsoft.com/es-es/windows/win32/api/" rel="noopener noreferrer"&gt;Win32&lt;/a&gt;, &lt;a href="https://www.gtk.org/" rel="noopener noreferrer"&gt;Gtk&lt;/a&gt;, &lt;a href="https://www.qt.io/" rel="noopener noreferrer"&gt;Qt&lt;/a&gt;, o &lt;a href="https://wxwidgets.org/" rel="noopener noreferrer"&gt;wxWidgets&lt;/a&gt;, comparten todas el mismo módulo base para el dibujo de la interfaz gráfica, algo de lo que se abstraen completamente.&lt;/p&gt;

&lt;p&gt;Pero una vez que una app se construye sobre uno de estos &lt;strong&gt;toolkits&lt;/strong&gt;, a no ser que esté &lt;a href="https://es.wikipedia.org/wiki/Modelo%E2%80%93vista%E2%80%93controlador" rel="noopener noreferrer"&gt;muy bien diseñada&lt;/a&gt;, va a estar atada a él. Y aún así, un &lt;strong&gt;port&lt;/strong&gt; a otro &lt;strong&gt;toolkit&lt;/strong&gt; tomará un considerable esfuerzo.&lt;/p&gt;

&lt;p&gt;La pregunta entonces es: ¿realmente son tan diferentes los estos módulos de interfaz gráfica como para requerir código totalmente distinto?&lt;/p&gt;

&lt;p&gt;Vamos a ver cómo podemos crear una pequeña interfaz gráfica para una app en C#, con la desaparecida (excepto para Windows) Windows.Forms.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;panel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Panel&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Dock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DockStyle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fill&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;btTop&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Top"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DockStyle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Top&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;btBottom&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Bottom"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DockStyle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bottom&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;btLeft&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Left"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DockStyle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Left&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;btRight&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Right"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DockStyle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Right&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;btCenter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Text&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Center"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dock&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;DockStyle&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Center&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Controls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;btTop&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Controls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;btBottom&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Controls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;btLeft&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Controls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;btRight&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Controls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;btCenter&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y ahora, otra en Java, utilizando Swing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;panel&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JPanel&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setLayout&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;BorderLayout&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;btTop&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JButton&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"Top"&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;btBottom&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JButton&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"Bottom"&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;btRight&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JButton&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"Left"&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;btLeft&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JButton&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"Right"&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;btCenter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;JButton&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"Center"&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;btTop&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;BorderLayout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NORTH&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;btBottom&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;BorderLayout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;SOUTH&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;btRight&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;BorderLayout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;EAST&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;btLeft&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;BorderLayout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;WEST&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt; &lt;span class="n"&gt;btCenter&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;BorderLayout&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;CENTER&lt;/span&gt; &lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;¿Cómo? ¿Que esos son &lt;strong&gt;toolkits&lt;/strong&gt; muy antiguos? Vale, veamos &lt;a href="https://avaloniaui.net/" rel="noopener noreferrer"&gt;Avalonia&lt;/a&gt; para C#:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;btCenter&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Center"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;panel&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;DockPanel&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;LastChildFill&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;btTop&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Top"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;btBottom&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Bottom"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;btLeft&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Left"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;btRight&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Button&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Content&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Right"&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="n"&gt;DockPanel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetDock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;btTop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Top&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;DockPanel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetDock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;btBottom&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bottom&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;DockPanel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetDock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;btLeft&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Left&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;DockPanel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SetDock&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;btRight&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Dock&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Right&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;btTop&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;btBottom&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;btLeft&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;btRight&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Children&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;btCenter&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esta no es la única forma de disponer controles gráficos en una app. También se pueden crear paneles unos dentro de otros, en vertical u horizontal, o utilizar una disposición de cuadrícula (&lt;strong&gt;grid&lt;/strong&gt;). Todas esas posibilidades están disponibles en todos los &lt;strong&gt;toolkits&lt;/strong&gt; gráficos... y sin embargo, todas ellas se llaman de forma total o ligeramente distinta.&lt;/p&gt;

&lt;p&gt;Y es que el problema es ese. Nadie se preocupa por una estandarización o compatibilidad. Cuando Google desarrolló Android, ya existían numerosos &lt;strong&gt;toolkits&lt;/strong&gt; gráficos disponibles, entre ellos algunos con tanta solvencia como &lt;strong&gt;Qt&lt;/strong&gt;, por poner un ejemplo. Y sin embargo, resolvieron crear el suyo propio. Desde cero. Soportando las mismas características. Pero, claro está, con nombres distintos. Y construcciones ligeramente distintas.&lt;/p&gt;

&lt;p&gt;Uno de los consejos que se da para desarrolladores es: &lt;strong&gt;no reinventes la rueda&lt;/strong&gt;. Excepto que lo estés haciendo para aprender, claro. Y sin embargo, cada vez que una nueva plataforma (cualquiera), soporta una vista gráfica, acaba desarrollando un nuevo &lt;strong&gt;toolkit&lt;/strong&gt; desde cero. Con nombres total o ligeramente distintos, pero soportando exactamente las mismas funcionalidades.&lt;/p&gt;

&lt;p&gt;No puedo dejar de mencionar específicamente a uno de los &lt;strong&gt;toolkits&lt;/strong&gt; más odiosos en este sentido: &lt;a href="https://www.gtk.org/" rel="noopener noreferrer"&gt;gtk&lt;/a&gt;. Como muestra un botón: no puedes (o al menos, no debes), cambiar colores de ventanas o botones. Ellos saben mejor que tú cuál es la interfaz perfecta (utilizan este tipo de frases como "&lt;strong&gt;no less than perfect user interfaces&lt;/strong&gt;"). Este virtuosismo permea también a cómo programar una interfaz con Gtk. De hecho, una app hecha con Gtk 2 será totalmente incompatible con Gtk 3, y a su vez, lo mismo para una con Gtk 3 hacia Gtk 4. Portar una app de una versión a otra es un laberinto de APIs obsoletas, funcionalidades refactorizadas, y cambios tan significativos como que los paneles (en Gtk son cajas, &lt;strong&gt;Box&lt;/strong&gt;) han pasado de ser clases separadas para &lt;strong&gt;HBox&lt;/strong&gt; (horizontal) y &lt;strong&gt;VBox&lt;/strong&gt; (vertical), a ser una sola clase &lt;strong&gt;Box&lt;/strong&gt; con un parámetro en el constructor, &lt;strong&gt;Orientation.Vertical&lt;/strong&gt;, u &lt;strong&gt;Orientation.Horizontal&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Necesitamos estandarización. Especialmente, si las funcionalidades son las mismas, no es necesario, y de hecho, ni siquiera es aconsejable, crear versiones con interfaces distintas.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1g5b6ju2u6o285jqix2z.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F1g5b6ju2u6o285jqix2z.jpg" alt="ICeberg representando una interfaz mínima" width="275" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Recordemos la analogía del iceberg, de manera que las interfaces deben ser mínimas independientemente de su implementación; y también que el primer lenguaje de programación orientado a objetos, &lt;a href="https://en.wikipedia.org/wiki/Simula" rel="noopener noreferrer"&gt;&lt;strong&gt;Simula&lt;/strong&gt;&lt;/a&gt;, estaba orientado a la simulación, por ejemplo, de piezas de un motor, de manera que distintas piezas podían intercambiarse... solo si soportaban la misma interfaz, claro.&lt;/p&gt;

</description>
      <category>spanish</category>
      <category>programming</category>
      <category>softwareengineering</category>
      <category>standards</category>
    </item>
    <item>
      <title>¿"Ingeniería" del software?</title>
      <dc:creator>Baltasar García Perez-Schofield</dc:creator>
      <pubDate>Mon, 27 Jul 2026 11:23:00 +0000</pubDate>
      <link>https://dev.to/baltasarq/ingenieria-del-software-6g4</link>
      <guid>https://dev.to/baltasarq/ingenieria-del-software-6g4</guid>
      <description>&lt;p&gt;El mayor reto de ingeniería del software nunca ha sido la IA. Siempre se ha tratado de convertir un "desarrollo artesano", en un proceso de ingeniería similar a la construcción, a la mecánica, o cualquier otra. Y si se quiere obtener esto, necesitamos exactamente aquello en lo que nadie está invirtiendo esfuerzo: estandarización. Porque inevitablemente, si quisiéramos apuntar a un proceso de ingeniería, necesitaríamos de algún proceso de montaje o composición de piezas. Y esas piezas son precisamente lo que no tenemos.&lt;/p&gt;

&lt;p&gt;El primer proceso de ingeniería del software era el &lt;em&gt;top-down&lt;/em&gt;, o también llamado &lt;a href="https://es.wikipedia.org/wiki/Divide_y_vencer%C3%A1s" rel="noopener noreferrer"&gt;"divide y vencerás"&lt;/a&gt;, de manera que el algoritmo se divide en procedimientos y funciones. Se presentan dos problemas: el primero, que nadie coincide en qué procedimientos utilizar, y el segundo, que las aplicaciones, al margen de que la construcción de software, siguieron requiriendo más funcionalidad, haciéndose más y más complejas.&lt;/p&gt;

&lt;p&gt;El siguiente hito fue el de los módulos. Los módulos serían colecciones de funciones y procedimientos, agrupando funcionalidad común (recordemos, &lt;a href="https://es.wikipedia.org/wiki/Acoplamiento_(inform%C3%A1tica)" rel="noopener noreferrer"&gt;alta cohesión, y bajo acoplamiento&lt;/a&gt;). Por ejemplo, en nuestra aplicación podemos crear módulos matemáticos, otros de interfaz de usuario, otro de creación de &lt;em&gt;logs&lt;/em&gt;... Y lo mejor es que, para futuros proyectos, podemos reutilizar estos módulos.&lt;/p&gt;

&lt;p&gt;No es que el proceso de divide y vencerás debiera eliminarse, sino que tenemos agrupamientos de más alto nivel que son los propios módulos.&lt;/p&gt;

&lt;p&gt;Pero la cosa no cuajó: el problema es que cada uno tenía una idea distinta sobre qué módulos crear, y si estos debieran ser de alto nivel o bajo nivel... ¿los de alto nivel deben componerse a partir de aquellos de alto nivel? Con el tiempo, se crearon repositorios de módulos, pero difícilmente se extendió una reutilización de estos módulos.&lt;/p&gt;

&lt;p&gt;Y además, volvemos a la problemática anterior: independientemente de que el proceso de ingeniería de software estuviese maduro o no, las aplicaciones seguían subiendo en cuanto a funcionalidad y complejidad.&lt;/p&gt;

&lt;p&gt;El siguiente hito fue la &lt;a href="https://es.wikipedia.org/wiki/Programaci%C3%B3n_orientada_a_objetos" rel="noopener noreferrer"&gt;POO (programación orientada a objetos)&lt;/a&gt;. Los módulos se transforman así en clases, que aúnan no solo procedimientos y funciones, sino también los propios datos. La encapsulación inherente del paradigma iba a resolver automáticamente el problema de la cohesión y acoplamiento. Se podrían tener repositorios de clases que podrían reutilizarse para cada funcionalidad.&lt;/p&gt;

&lt;p&gt;Sin entrar en detalles, la POO no fue la panacea que se esperaba. Los problemas seguían siendo los mismos: al final, cada programador tenía una idea distinta de qué clases debían componer la aplicación, del nivel de abstracción necesario, y sí, las aplicaciones siguen evolucionando en cuanto a funcionalidad y complejidad.&lt;/p&gt;

&lt;p&gt;Y sorprendentemente, se descubrió que la POO no evitaba automáticamente, como se esperaba, que no hubiera acoplamiento entre clases, o que las clases fueran piezas genéricas que podrán transportarse de un proyecto a otro. De nuevo, la reusabilidad emergió como un problema, sin que la POO pudiera evitarlo. No, tampoco aparecieron los repositorios de clases. Aparecieron principios de programación como los &lt;a href="https://es.wikipedia.org/wiki/SOLID" rel="noopener noreferrer"&gt;SOLID&lt;/a&gt;, o los &lt;a href="https://es.wikipedia.org/wiki/Patr%C3%B3n_de_dise%C3%B1o" rel="noopener noreferrer"&gt;patrones de diseño&lt;/a&gt;, que tratan de guiar al programador para intentar mitigar estos problemas.&lt;/p&gt;

&lt;p&gt;Finalmente, estamos en el hito de la &lt;a href="https://es.wikipedia.org/wiki/Desarrollo_%C3%A1gil_de_software" rel="noopener noreferrer"&gt;programación ágil&lt;/a&gt;. Se asume que el desarrollo del software es un proceso artesano, y lo que se intenta es delimitar y controlar para que no "se vaya de madre". Pero, ¿hemos alcanzado algún hito de reutilización? No en mi opinión.&lt;/p&gt;

&lt;p&gt;Ahora que hemos repasado (muy por encima), la evolución del desarrollo práctico de software, ahondaremos en próximas entradas sobre si los desarrolladores de software tienen este problema interiorizado y están haciendo algo o no.&lt;/p&gt;

</description>
      <category>spanish</category>
      <category>programming</category>
      <category>softwareengineering</category>
      <category>standards</category>
    </item>
    <item>
      <title>Z80: 50 años han pasado ya</title>
      <dc:creator>Baltasar García Perez-Schofield</dc:creator>
      <pubDate>Sun, 19 Jul 2026 10:41:29 +0000</pubDate>
      <link>https://dev.to/baltasarq/z80-50-anos-han-pasado-ya-1fc5</link>
      <guid>https://dev.to/baltasarq/z80-50-anos-han-pasado-ya-1fc5</guid>
      <description>&lt;p&gt;En junio de 2024, &lt;a href="https://dev.to/baltasarq/descansa-en-paz-z80-34mj"&gt;Zilog decidió dejar de fabricar el z80&lt;/a&gt;, aunque esto &lt;a href="https://www.cpu-world.com/CPUs/Z80/index.html" rel="noopener noreferrer"&gt;no quiere decir que el Z80 dejase de existir&lt;/a&gt;: por ejemplo, Sharp todavía lo vende con la identificación LH0080, y NEC hace lo propio con la etiqueta D780C-1.&lt;/p&gt;

&lt;p&gt;El Z80 era compatible con el &lt;a href="https://es.wikipedia.org/wiki/Intel_8080" rel="noopener noreferrer"&gt;Intel 8080&lt;/a&gt;. ¿Por qué entonces, si ya existía este procesador, Zilog se "animó" a crear una variante compatible? Lo cierto es que el i8080 era bastante enrevesado en cuanto a la forma de alimentarlo: necesitaba varios voltajes. El Z80, sin embargo, solo necesitaba alimentación de 5V, una sola línea de reloj (CLK), y era más rápido.&lt;/p&gt;

&lt;h2&gt;
  
  
  Funcionamiento interno
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Registro&lt;/th&gt;
&lt;th&gt;Funcionalidad&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;Registro acumulador.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;Registro de uso libre.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;c&lt;/td&gt;
&lt;td&gt;Registro de uso libre.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;Registro de uso libre.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;Registro de uso libre.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;H&lt;/td&gt;
&lt;td&gt;Parte alta de dir. RAM.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;L&lt;/td&gt;
&lt;td&gt;Parte baja de dir. RAM.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IX&lt;/td&gt;
&lt;td&gt;Registro de índice.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IY&lt;/td&gt;
&lt;td&gt;Registro de índice.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;SP&lt;/td&gt;
&lt;td&gt;Stack pointer.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;PC&lt;/td&gt;
&lt;td&gt;Program counter.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Todos los registros eran de 8 bits, excepto los registros de índice &lt;strong&gt;IX&lt;/strong&gt; e &lt;strong&gt;IY&lt;/strong&gt;, el contador de programa &lt;strong&gt;PC&lt;/strong&gt;, y el puntero de la pila de llamadas, &lt;strong&gt;SP&lt;/strong&gt;, que son de 16 bits. Pero además, el resto de registros se pueden combinar. Por ejemplo, para acceder a una dirección de memoria, se colocan los 8 bits más bajos en &lt;strong&gt;L&lt;/strong&gt;, y los 8 bits más altos en &lt;strong&gt;H&lt;/strong&gt;, de forma que se obtiene una dirección de memoria de 16 bits (2^16 o 65536 bytes/64 K).&lt;/p&gt;

&lt;p&gt;Además, los registros &lt;strong&gt;B&lt;/strong&gt; y &lt;strong&gt;C&lt;/strong&gt; se pueden utilizar juntos como registros de 16 bits, si se utiliza el nombre &lt;strong&gt;BC&lt;/strong&gt;, y lo mismo para &lt;strong&gt;D&lt;/strong&gt; y &lt;strong&gt;E&lt;/strong&gt;, que puede ser utilizado como &lt;strong&gt;DE&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Los registros &lt;strong&gt;IX&lt;/strong&gt; e &lt;strong&gt;IY&lt;/strong&gt; son nuevos, permitiendo funcionar como índices. Supongamos que necesitas copiar una cadena de caracteres en la posición de memoria 00000000FFFFFFFF, en otra posición de memoria que sería 00000001FFFFFFFF. El primer valor se copiaría en &lt;strong&gt;IX&lt;/strong&gt;, mientras que se haría lo propio con el segundo en &lt;strong&gt;IY&lt;/strong&gt;. Ahora puedes ir copiando el valor apuntado por uno en la posición apuntado en el otro, e ir incrementando ambos.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;8 bits bajos&lt;/th&gt;
&lt;th&gt;8 bits altos&lt;/th&gt;
&lt;th&gt;Registro combinado&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;BC&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;D&lt;/td&gt;
&lt;td&gt;E&lt;/td&gt;
&lt;td&gt;DE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;H&lt;/td&gt;
&lt;td&gt;L&lt;/td&gt;
&lt;td&gt;HL&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Es decir, que si se quiere hacer algún cálculo que involucre 16 bits, se usan &lt;strong&gt;BC&lt;/strong&gt;, o &lt;strong&gt;DE&lt;/strong&gt;, y si se quiere acceder a una determinada posición de memoria, &lt;strong&gt;HL&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Compatibilidad y legado
&lt;/h2&gt;

&lt;p&gt;El uso del z80 se extendió rápidamente al ser un chip tan versátil. Esto produjo una situación en la que muchos programas podían ser compatibles a nivel de código ejecutable.&lt;/p&gt;

&lt;p&gt;Así, &lt;a href="https://es.wikipedia.org/wiki/Gary_Kildall" rel="noopener noreferrer"&gt;Gary Kildall&lt;/a&gt;, programó &lt;a href="https://es.wikipedia.org/wiki/CP/M" rel="noopener noreferrer"&gt;CP/M&lt;/a&gt; (el antepasado del sistema operativo &lt;a href="https://es.wikipedia.org/wiki/MS-DOS" rel="noopener noreferrer"&gt;MS-DOS&lt;/a&gt;) para Z80, vendiéndolo a través de su nueva empresa &lt;a href="https://es.wikipedia.org/wiki/Digital_Research" rel="noopener noreferrer"&gt;Digital Research&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Por cuestiones de desacuerdo en las licencias, no creó  CP/M para el &lt;a href="https://es.wikipedia.org/wiki/IBM_PC" rel="noopener noreferrer"&gt;IBM-PC&lt;/a&gt; con su &lt;a href="https://es.wikipedia.org/wiki/Intel_8086_y_8088" rel="noopener noreferrer"&gt;i8088&lt;/a&gt;, y al final se adaptó QDOS (el rápido y sucio sistema operativo, o &lt;em&gt;Quick &amp;amp; Dirty Operating System&lt;/em&gt;) para la máquina. Posteriormente, Digital Research desarrollaría DR-DOS, compatible con MS-DOS. Pero eso es otra historia.&lt;/p&gt;

&lt;p&gt;Para CP/M se crearon lenguajes de programación, bases de datos... fue tremendamente popular, ya que surgieron multitud de máquinas cuyo corazón era el Z80, y para el que CP/M era muy fácilmente adaptable.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://es.wikipedia.org/wiki/Altair_BASIC" rel="noopener noreferrer"&gt;Altair BASIC&lt;/a&gt; fue creado originalmente por Bill Gates para el &lt;a href="https://es.wikipedia.org/wiki/Altair_8800" rel="noopener noreferrer"&gt;Altair 8080&lt;/a&gt;, antes de crear Microsoft. Ocupaba 4K de memoria. Pero la multitud de microordenadores que surgieron utilizando el Z80 hizo que &lt;a href="https://es.wikipedia.org/wiki/Microsoft_BASIC" rel="noopener noreferrer"&gt;Microsoft BASIC&lt;/a&gt;, directamente derivado del anterior, tuviera docenas de versiones adaptadas a ellos, creando máquinas cuyos programas en BASIC en binario eran compatibles entre sí, o facilitando la creación de un estándar como tal, el MSX.&lt;/p&gt;

&lt;p&gt;...y por supuesto, fue el corazón del &lt;a href="https://es.wikipedia.org/wiki/Sinclair_ZX_Spectrum#Sinclair_ZX_Spectrum_+128" rel="noopener noreferrer"&gt;Investrónica/Sinclair Spectrum + 128k&lt;/a&gt;, el mejor de los microordenadores de 8 bits de los 80. Como curiosidad, es interesante comentar que existe un nuevo modelo de ZX Spectrum, el &lt;a href="https://en.wikipedia.org/wiki/ZX_Spectrum_Next" rel="noopener noreferrer"&gt;ZX Spectrum Next&lt;/a&gt;, y este lleva un Z80N. capaz de correr incluso a 28 Mhz., en contraste con los 3.5 Mhz. del original. Eso sí, es una recreación moderna del Z80 mediante una &lt;a href="https://es.wikipedia.org/wiki/Matriz_de_puerta_programable_en_campo" rel="noopener noreferrer"&gt;FPGA&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Lo siguiente es el código ensamblador para el "¡Hola, mundo!" en el Speccy. No hace uso de la rutina en ROM &lt;code&gt;print&lt;/code&gt; del BASIC, sino que muestra una cadena carácter a carácter, mediante una rutina en ROM de muy bajo nivel (la $10).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nasm"&gt;&lt;code&gt;&lt;span class="nf"&gt;org&lt;/span&gt; &lt;span class="kc"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;8000&lt;/span&gt;
  &lt;span class="nf"&gt;ld&lt;/span&gt; &lt;span class="nv"&gt;bc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;STR_HELLO&lt;/span&gt;        &lt;span class="c1"&gt;; Carga en BC la dirección de la cadena&lt;/span&gt;

&lt;span class="nl"&gt;SHOW_CHAR:&lt;/span&gt;                &lt;span class="c1"&gt;; Cada iteración muestra un carácter.&lt;/span&gt;
  &lt;span class="nf"&gt;ld&lt;/span&gt; &lt;span class="nv"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;bc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;              &lt;span class="c1"&gt;; Carga el carácter actual en A&lt;/span&gt;
  &lt;span class="nf"&gt;cp&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;                    &lt;span class="c1"&gt;; ¿El carácter en A es un cero?&lt;/span&gt;
  &lt;span class="nf"&gt;jr&lt;/span&gt; &lt;span class="nv"&gt;z&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;END&lt;/span&gt;               &lt;span class="c1"&gt;; Si el resultado es true, salta a END&lt;/span&gt;
  &lt;span class="nf"&gt;rst&lt;/span&gt; &lt;span class="kc"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;                 &lt;span class="c1"&gt;; Llama a la rutina en ROM que muestra el carácter A por pantalla&lt;/span&gt;
  &lt;span class="nf"&gt;inc&lt;/span&gt; &lt;span class="nv"&gt;bc&lt;/span&gt;                  &lt;span class="c1"&gt;; Incrementa la dirección en BC en 1&lt;/span&gt;
  &lt;span class="nf"&gt;jr&lt;/span&gt; &lt;span class="nv"&gt;SHOW_CHAR&lt;/span&gt;            &lt;span class="c1"&gt;; Salta a SHOW_CHAR&lt;/span&gt;

&lt;span class="nl"&gt;END:&lt;/span&gt;
  &lt;span class="nf"&gt;ret&lt;/span&gt;                     &lt;span class="c1"&gt;; Terminar el programa, y volver&lt;/span&gt;

&lt;span class="nl"&gt;STR_HELLO:&lt;/span&gt;                &lt;span class="c1"&gt;; Define la cadena de caracteres terminada en 0&lt;/span&gt;
  &lt;span class="nf"&gt;defb&lt;/span&gt; &lt;span class="err"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;Hola&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;mundo&lt;/span&gt;&lt;span class="err"&gt;!"&lt;/span&gt;
  &lt;span class="nf"&gt;defb&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El Zilog Z80 fue, por tanto, un pilar fundamental en el desarrollo de la informática, que finalmente, con la aparición de los microordenadores, se introducirá en los hogares para su uso doméstico, algo impensable en los 70.&lt;/p&gt;

</description>
      <category>spanish</category>
      <category>retro</category>
      <category>z80</category>
      <category>spectrum</category>
    </item>
    <item>
      <title>Ensamblando DotNet IL</title>
      <dc:creator>Baltasar García Perez-Schofield</dc:creator>
      <pubDate>Wed, 15 Jul 2026 20:09:14 +0000</pubDate>
      <link>https://dev.to/baltasarq/ensamblando-dotnet-il-4ion</link>
      <guid>https://dev.to/baltasarq/ensamblando-dotnet-il-4ion</guid>
      <description>&lt;p&gt;Vimos en la primera parte de esta serie que podemos fácilmente tomar un ensamblado compilado con C# (o con el lenguaje de .NET que queramos), y desensamblarlo para ver su código.&lt;/p&gt;

&lt;p&gt;¿Podemos realizar el paso contrario? No estaría mal poder ensamblar código directamente. Veamos cómo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;asm&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AssemblyDefinition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateAssembly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AssemblyNameDefinition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt;
                                &lt;span class="s"&gt;"tmp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                &lt;span class="n"&gt;ModuleKind&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Dll&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con esto ya tenemos un ensamblado creado. Pero si queremos ver cualquier cosa que hagamos, vamos a tener que referenciar &lt;strong&gt;Console&lt;/strong&gt;.&lt;em&gt;WriteLine()&lt;/em&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;consoleRef&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AssemblyNameReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                       &lt;span class="s"&gt;"System.Console"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                       &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Version&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;asm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MainModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AssemblyReferences&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;consoleRef&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora creemos una clase llamada &lt;strong&gt;App&lt;/strong&gt; (va a tener un constructor vacío):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;cls&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TypeDefinition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                 &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="n"&gt;clsName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="n"&gt;TypeAttrs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Class&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;TypeAttrs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Public&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                 &lt;span class="n"&gt;asm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MainModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TypeSystem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Add a parameterless constructor&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;ctor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;MethodDefinition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;".ctor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;MthAttrs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Public&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MthAttrs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HideBySig&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MthAttrs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SpecialName&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;MthAttrs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SpecialName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="n"&gt;asm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MainModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TypeSystem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Void&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Methods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;ctor&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Import from System.Object type&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;objectCtor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;asm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MainModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ImportReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                       &lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;object&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;
                       &lt;span class="nf"&gt;GetConstructor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EmptyTypes&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Constructor body must call base class constructor&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;il&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetILProcessor&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="n"&gt;il&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;il&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ldarg_0&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;                      &lt;span class="c1"&gt;// load 'this'&lt;/span&gt;
&lt;span class="n"&gt;il&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;il&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;objectCtor&lt;/span&gt; &lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="n"&gt;il&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;il&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ret&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;asm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MainModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;toret&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sí, el hecho de tener que crear un constructor vacío hace que para crear una clase sea necesario bastante código. En el futuro, meteremos este código en un método reusable, claro. Lo más importante son la primera y la última línea. En la primera, es donde se crea la clase (un &lt;strong&gt;TypeDefinition&lt;/strong&gt;), y en la última se toma el módulo principal del ensamblado, y se añade el nuevo tipo allí.&lt;/p&gt;

&lt;p&gt;Además, vemos por primera vez código IL siendo creado para un método. Siempre lo haremos de la misma manera: tomamos de la propiedad &lt;code&gt;Body&lt;/code&gt; del método el procesador de IL, mediante el método &lt;code&gt;GetILProcessor()&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;El código que estamos ensamblando es el siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ctor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ldarg&lt;/span&gt;&lt;span class="mf"&gt;.0&lt;/span&gt;            &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;cargar&lt;/span&gt; &lt;span class="s"&gt;"this"&lt;/span&gt; &lt;span class="n"&gt;en&lt;/span&gt; &lt;span class="n"&gt;la&lt;/span&gt; &lt;span class="n"&gt;pila&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ctor&lt;/span&gt;   &lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;ret&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ya sabemos que la pila es &lt;em&gt;el último que entra es el primero que sale&lt;/em&gt; o &lt;strong&gt;LIFO&lt;/strong&gt; (&lt;em&gt;last in, first out&lt;/em&gt;). También sabemos que los métodos llevan un parámetro oculto que es el objeto que está ejecutando el método, &lt;code&gt;this&lt;/code&gt;. Aquellas instrucciones que empiezan por &lt;code&gt;ld&lt;/code&gt; (&lt;em&gt;load&lt;/em&gt;) son equivalentes a &lt;em&gt;push&lt;/em&gt;, o meter en la pila. Por ejemplo, &lt;code&gt;ldstr&lt;/code&gt; introduce una cadena de caracteres en la pila. Las instrucciones que empiezan por &lt;code&gt;st&lt;/code&gt; (&lt;em&gt;store&lt;/em&gt;), son equivalentes a &lt;em&gt;pop&lt;/em&gt;. Por ejemplo, &lt;code&gt;stfld&lt;/code&gt; guarda el valor en el tope de la pila en una campo de un objeto.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ldarg&lt;/code&gt; mete un argumento (identificado por su número de posición) en la pila. Así, &lt;code&gt;ldarg 0&lt;/code&gt; metería el primer argumento del método en la pila. Meter el primer argumento en la pila es tan común, que existe un opcode específico: &lt;code&gt;ldarg.0&lt;/code&gt;. Lo que hace (lo has adivinado), es meter en la pila el primer argumento del método, que ya hemos visto que es &lt;code&gt;this&lt;/code&gt;. &lt;code&gt;call&lt;/code&gt; permite llamar a un método en un objeto cualquiera. &lt;code&gt;ret&lt;/code&gt; termina el método. Todos los métodos deben tener al menos un &lt;code&gt;ret&lt;/code&gt;... ¿sabes que si no incluyes un &lt;code&gt;ret&lt;/code&gt;, .NET sigue ejecutando la memoria siguiente, tomándola como instrucciones? ¿Un poco "cutre", no?&lt;/p&gt;

&lt;p&gt;Así, el constructor de &lt;strong&gt;Object&lt;/strong&gt; es un constructor sin parámetros... si no contamos con &lt;code&gt;this&lt;/code&gt;, claro está. Los parámetros deben tomarse de la pila, y en caso, de necesitar más de uno, será necesario meterlos en la pila en el orden inverso.&lt;/p&gt;

&lt;p&gt;El código en C# sería el siguiente:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;App&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;O lo que es lo mismo...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;¿Metemos un "¡Hola, mundo!"? Veamos, las instrucciones que necesitaremos ya las hemos visto en su mayoría. Necesitaremos llamar a &lt;code&gt;Console.WriteLine()&lt;/code&gt; con una cadena de caracteres como parámetro. Esta cadena de caracteres tendrá que meterse en la pila, antes de la llamada, claro.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"¡Hola, mundo!"&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Repasemos entonces lo que es necesario hacer: meter en la pila la cadena de caracteres "¡Hola, mundo!"; hacer la llamada &lt;code&gt;Console.WriteLine()&lt;/code&gt;, y finalmente, retornar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight cpp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="n"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;ldstr&lt;/span&gt; &lt;span class="s"&gt;"¡Hola, mundo!"&lt;/span&gt;
        &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="n"&gt;System&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;ret&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Lo primero de todo, necesitamos localizar el método &lt;code&gt;WriteLine()&lt;/code&gt; en la consola.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;consoleRef&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MainModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AssemblyReferences&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="nf"&gt;FirstOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"System.Console"&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;??&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TypeLoadException&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="s"&gt;"missing System.Console assembly reference"&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;consoleType&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;TypeReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                          &lt;span class="s"&gt;"System"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="s"&gt;"Console"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="n"&gt;methodInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="n"&gt;consoleRef&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;writeLineMethod&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;MethodReference&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                          &lt;span class="s"&gt;"WriteLine"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="n"&gt;methodInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TypeSystem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Void&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                          &lt;span class="n"&gt;consoleType&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;writeLineMethod&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parameters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;ParameterDefinition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;methodInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TypeSystem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;String&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Así que necesitamos crear un método &lt;code&gt;Main&lt;/code&gt;, dentro de nuestra clase &lt;strong&gt;App&lt;/strong&gt;. Necesitamos las tres instrucciones que hemos visto un poco más arriba.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;mth&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;MethodDefinition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;mthName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                &lt;span class="n"&gt;attrs&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                                &lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TypeSystem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Void&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="n"&gt;cls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Methods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;mth&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;il&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mth&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetILProcessor&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="n"&gt;il&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;il&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ldstr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"¡Hola, mundo!"&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;il&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;il&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Call&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;writeLineMethod&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;il&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;il&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;OpCodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Ret&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora marcamos el método &lt;code&gt;Main()&lt;/code&gt; como el punto de entrada del ensamblado, y escribirmos el ensamblado terminado en disco.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;asm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EntryPoint&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;mth&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="n"&gt;asm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"hola.dll"&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Vale. Ahora solo queda ejecutarlo, y comprobar que tenemos el ensamblado creado. Y una vez comprobado... ¡lo ejecutamos!&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ dotnet run
$ ls *.dll
hola.dll
$ dotnet hola.dll
¡Hola, mundo!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;¿No te parece fascinante? ¡A mi sí!&lt;/p&gt;

</description>
      <category>spanish</category>
      <category>dotnet</category>
      <category>chsarp</category>
      <category>mono</category>
    </item>
    <item>
      <title>Decompilando C#</title>
      <dc:creator>Baltasar García Perez-Schofield</dc:creator>
      <pubDate>Fri, 10 Jul 2026 09:24:04 +0000</pubDate>
      <link>https://dev.to/baltasarq/decompilando-c-j9o</link>
      <guid>https://dev.to/baltasarq/decompilando-c-j9o</guid>
      <description>&lt;p&gt;&lt;a href="https://en.wikipedia.org/wiki/C_Sharp_(programming_language)" rel="noopener noreferrer"&gt;C#&lt;/a&gt; compila a una máquina virtual, llamada &lt;a href="https://en.wikipedia.org/wiki/Common_Language_Runtime" rel="noopener noreferrer"&gt;CLR&lt;/a&gt; (&lt;em&gt;Common Language Runtime&lt;/em&gt;), en código ensamblador llamado originalmente &lt;a href="https://en.wikipedia.org/wiki/Common_Intermediate_Language" rel="noopener noreferrer"&gt;MSIL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;El proyecto &lt;a href="https://en.wikipedia.org/wiki/Mono_(software)" rel="noopener noreferrer"&gt;Mono&lt;/a&gt; nació como un versión multiplataforma de C#. En 2016 la empresa creadora, Ximian, fue comprada por Microsoft, y en 2024 Microsoft cedió el proyecto al proyecto &lt;a href="https://en.wikipedia.org/wiki/Wine_(software)" rel="noopener noreferrer"&gt;Wine&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Así, aunque Mono parece obsoleto hoy en día, el subproyecto CECIL de Mono se mantiene al día, conformándose como una excelente herramienta para analizar IL.&lt;/p&gt;

&lt;p&gt;Así, si queremos crear un decompilador, solo tenemos que preparar un proyecto que incluya el paquete NuGET Mono.Cecil.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ mkdir disasm
$ cd disasm
$ dotnet new console
$ dotnet package new Mono.Cecil
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Solo necesitamos una clase muy sencilla para decompilar.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Disasm&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;Instruction&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="nf"&gt;GetMethodInstructions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;assemblyPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;typeName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;methodName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;toret&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Array&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Instruction&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

        &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;assembly&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;AssemblyDefinition&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ReadAssembly&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;assemblyPath&lt;/span&gt; &lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MainModule&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Types&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FirstOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;typeName&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;Methods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FirstOrDefault&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;methodName&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;HasBody&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="k"&gt;true&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;toret&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="p"&gt;..&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Instructions&lt;/span&gt; &lt;span class="p"&gt;];&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;toret&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="nf"&gt;StrFromInstructions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Instruction&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                        &lt;span class="s"&gt;"\n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;instructions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                            &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s"&gt;$"&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Offset&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;X4&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpCode&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Operand&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ya solo necesitamos llamar a los métodos de la case con un nombre de ensamblado, otro de clase y finalmente, un nombre de método.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;App&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Decompile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;dllName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;clsName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;mthName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;instructions&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Disasm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetMethodInstructions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                                                &lt;span class="n"&gt;dllName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;clsName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;mthName&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"DisAsm\n"&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;Disasm&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StrFromInstructions&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;instructions&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Length&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"Please provide: file_name class_name mth_name"&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nf"&gt;Decompile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Y ahora podemos ejecutarlo, por ejemplo, utilizando el propio ejecutable, y dirigirlo al método &lt;strong&gt;Disasm&lt;/strong&gt;.&lt;em&gt;StrFromInstructions&lt;/em&gt;().&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;dotnet run bin/Debug/net11.0/disasm.dll Disasm StrFromInstructions
&lt;span class="go"&gt;DisAsm

0000: nop 
0001: ldstr 

0006: ldarg.0 
&lt;/span&gt;&lt;span class="gp"&gt;0007: ldsfld System.Func`2&amp;lt;Mono.Cecil.Cil.Instruction,System.String&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Disasm/&amp;lt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;c::&amp;lt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;9__1_0
&lt;span class="go"&gt;000C: dup 
&lt;/span&gt;&lt;span class="gp"&gt;000D: brtrue.s IL_0026: call System.Collections.Generic.IEnumerable`1&amp;lt;!!1&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;System.Linq.Enumerable::Select&amp;lt;Mono.Cecil.Cil.Instruction,System.String&amp;gt;&lt;span class="o"&gt;(&lt;/span&gt;System.Collections.Generic.IEnumerable&lt;span class="sb"&gt;`&lt;/span&gt;1&amp;lt;&lt;span class="o"&gt;!!&lt;/span&gt;0&amp;gt;,System.Func&lt;span class="sb"&gt;`&lt;/span&gt;2&amp;lt;&lt;span class="o"&gt;!!&lt;/span&gt;0,!!1&amp;gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;000F: pop 
&lt;/span&gt;&lt;span class="gp"&gt;0010: ldsfld Disasm/&amp;lt;&amp;gt;&lt;/span&gt;c Disasm/&amp;lt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;c::&amp;lt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;9
&lt;span class="gp"&gt;0015: ldftn System.String Disasm/&amp;lt;&amp;gt;&lt;/span&gt;c::&amp;lt;StrFromInstructions&amp;gt;b__1_0&lt;span class="o"&gt;(&lt;/span&gt;Mono.Cecil.Cil.Instruction&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;001B: newobj System.Void System.Func`2&amp;lt;Mono.Cecil.Cil.Instruction,System.String&amp;gt;&lt;/span&gt;::.ctor&lt;span class="o"&gt;(&lt;/span&gt;System.Object,System.IntPtr&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;0020: dup 
&lt;/span&gt;&lt;span class="gp"&gt;0021: stsfld System.Func`2&amp;lt;Mono.Cecil.Cil.Instruction,System.String&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;Disasm/&amp;lt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;c::&amp;lt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;9__1_0
&lt;span class="gp"&gt;0026: call System.Collections.Generic.IEnumerable`1&amp;lt;!!1&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;System.Linq.Enumerable::Select&amp;lt;Mono.Cecil.Cil.Instruction,System.String&amp;gt;&lt;span class="o"&gt;(&lt;/span&gt;System.Collections.Generic.IEnumerable&lt;span class="sb"&gt;`&lt;/span&gt;1&amp;lt;&lt;span class="o"&gt;!!&lt;/span&gt;0&amp;gt;,System.Func&lt;span class="sb"&gt;`&lt;/span&gt;2&amp;lt;&lt;span class="o"&gt;!!&lt;/span&gt;0,!!1&amp;gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="gp"&gt;002B: call System.String System.String::Join(System.String,System.Collections.Generic.IEnumerable`1&amp;lt;System.String&amp;gt;&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="go"&gt;0030: stloc.0 
0031: br.s IL_0033: ldloc.0
0033: ldloc.0 
0034: ret
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con Mono.Cecil, podremos incluso generar nuestros propios ensamblados, modificando el ensamblado original. ¿Te apuntas?&lt;/p&gt;

</description>
      <category>spanish</category>
      <category>dotnet</category>
      <category>csharp</category>
      <category>mono</category>
    </item>
    <item>
      <title>¿Necesitas más velocidad en tu PC? ¡Pulsa el "turbo"!</title>
      <dc:creator>Baltasar García Perez-Schofield</dc:creator>
      <pubDate>Fri, 03 Jul 2026 08:05:37 +0000</pubDate>
      <link>https://dev.to/baltasarq/necesitas-mas-velocidad-en-tu-pc-pulsa-el-turbo-4ofi</link>
      <guid>https://dev.to/baltasarq/necesitas-mas-velocidad-en-tu-pc-pulsa-el-turbo-4ofi</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdytos3tmm5dcs4r6qeaq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fdytos3tmm5dcs4r6qeaq.jpg" alt="El botón " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El otro día, me sentí muy mayor. Un alumno explicaba cómo había creado desde cero un clon de un programa que solo existía para 16bits... sobre &lt;a href="https://es.wikipedia.org/wiki/MS-DOS" rel="noopener noreferrer"&gt;MS-DOS&lt;/a&gt;. Se trataba de una herramienta para simular una arquitectura de computador extremadamente simple, sin apenas registros excepto para la ULA (que solo suma), y 256 bytes de RAM en 16 palabras de 16 bits. Se parece a esta &lt;a href="https://ebalvis.github.io/Simulador-interactivo-de-maquina-simple/" rel="noopener noreferrer"&gt;Máquina Simple&lt;/a&gt;, aunque incluso era más recortada.&lt;/p&gt;

&lt;p&gt;El trabajo realizado era excelente. Pero empezó la charla hablando de las limitaciones de la herramienta que se utilizaba actualmente en la asignatura, remarcando que tenía que ser ejecutada con &lt;a href="https://es.wikipedia.org/wiki/DOSBox" rel="noopener noreferrer"&gt;DOSBox&lt;/a&gt;, y todo el conjunto era muy lento porque al fin y al cabo, "MS-DOS se ejecutaba a 300 Mhz"...&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flepq03q0o8i7wc9z61sz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flepq03q0o8i7wc9z61sz.png" alt="MS-DOS" width="550" height="275"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Miré brevemente, con disimulo, en derredor. Me di cuenta de que era más que probable que fuera el único en la sala que... primero, hubiera usado MS-DOS, y segundo, que se acordase de cómo funcionaba; y de que, desde luego, no corría a 300 Mhz. No sé por qué me acuerdo de estas cosas, pero lo de los 300 MHz ya vino en la época del arranque en popularidad de Windows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3gyb1kt6yuxhc7msrdb3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F3gyb1kt6yuxhc7msrdb3.jpg" alt="IBM PC" width="337" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El IBM PC nació como una arquitectura acompañando a un microprocesador Intel 8088, o i8088. El microprocesador que realmente "tocaba" era el &lt;a href="https://es.wikipedia.org/wiki/Intel_8086_y_8088" rel="noopener noreferrer"&gt;i8086, no el i8088&lt;/a&gt;, pero este procesador era "puro", con un bus de direcciones y de datos de 16 bits. En cambio, el i8088 era un microprocesador de 16 bits... que se comunicaba con el resto de la placa base a 8 bits. Esto quiere decir que cuando quería acceder a una posición de memoria, o escribir o leer un dato, primero mandaba 8 bits, y después los 8 bits restantes (a esto se le conoce como multiplexación en el tiempo).&lt;/p&gt;

&lt;p&gt;El IBM PC salió con el i8088 para abaratar costes, pues en aquella época las placas base de 8 bits eran muy comunes.&lt;/p&gt;

&lt;p&gt;Bueno, el caso es que el i8088 funcionaba a 5 Mhz (en realidad, unos 4.7 Mhz). El i8086 era capaz de funcionar con más velocidad, podía llegar incluso a 12 Mhz. Después llegó el &lt;a href="https://es.wikipedia.org/wiki/Intel_80286" rel="noopener noreferrer"&gt;i80286&lt;/a&gt;, que era capaz de llegar hasta los 25 Mhz.&lt;/p&gt;

&lt;p&gt;Después vendría el i80386, un micro con gestión de memoria incorporada, que podía ejecutar sistemas operativos "serios" como UNIX.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl7k7ddvot9olxojyai66.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fl7k7ddvot9olxojyai66.jpg" alt="Intel 80386" width="292" height="286"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Sí, estoy hablando de megaherzios, no de gigaherzios. Pero espera, que ahora llega lo más grande. El caso es que tú tenías tu software de gestión y tus juegos... Si te pasabas a un i80286, de repente, todo iba demasiado rápido. En el software de gestión muchas veces no lo notabas, pero los juegos se tornaban... injugables.&lt;/p&gt;

&lt;p&gt;Así que en el chásis tenías un botón, etiquetado "Turbo", que te permitía volver a la velocidad de la generación anterior. Por ejemplo, si tu procesador "corría" a 24 Mhz, pulsando en el botón "Turbo" volvía a los 12 Mhz, por ejemplo. Esto se hacía de múltiples maneras. Una de ellas, con el i80386, era desactivar su caché de 64Kb (que sí, que no eran Megabytes o Gigabytes...).&lt;/p&gt;

&lt;p&gt;Cuando salías del juego podías pulsar de nuevo el botón para que el ordenador corriera de nuevo a toda velocidad. Como el recurso empleado era por &lt;em&gt;hardware&lt;/em&gt;, los cambios eran inmediatos.&lt;/p&gt;

&lt;p&gt;Con el &lt;a href="https://es.wikipedia.org/wiki/Intel_80486" rel="noopener noreferrer"&gt;i80486&lt;/a&gt;... ¡podías llegar hasta a 100MHz! ¡Toma ya!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2uyojsojs7ae5q9m8c5x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F2uyojsojs7ae5q9m8c5x.png" alt="Windows 95" width="640" height="377"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Después llegó el &lt;a href="https://es.wikipedia.org/wiki/Intel_Pentium" rel="noopener noreferrer"&gt;Intel Pentium&lt;/a&gt;, que sí, ya podía correr a incluso a 300 Mhz. Intel estaba cansada de que sus competidores, como Cyrix o AMD, le copiarán impunemente el nombre de sus micros, pero no podía hacer nada porque los números no pueden registrarse. Así que cambió a Pentium, lo que vendría a rememorar que lo que "tocaba" era el 586. Para entonces en 1995, por todas partes el sistema operativo pasaba a ser &lt;a href="https://es.wikipedia.org/wiki/Windows_95" rel="noopener noreferrer"&gt;Windows 95&lt;/a&gt;, y solo los programadores, y raritos, seguíamos usando MS-DOS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw4m1p38f7h4xoroybmae.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fw4m1p38f7h4xoroybmae.png" alt=" " width="640" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Incluso las aplicaciones empezaban a traer ya un "modo gráfico", que aún ejecutándose sobre MS-DOS, permitía el uso de menús y algo más parecido a &lt;a href="https://es.wikipedia.org/wiki/WYSIWYG" rel="noopener noreferrer"&gt;WYSIWYG&lt;/a&gt;. Por ejemplo, &lt;a href="https://es.wikipedia.org/wiki/WordPerfect" rel="noopener noreferrer"&gt;WordPerfect 5.2&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fto9xlkka3kdmfarhdbsr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fto9xlkka3kdmfarhdbsr.jpg" alt="MS-DOS en Windows" width="600" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Además, programar para Windows era un suplicio (la biblia del momento para &lt;a href="https://archive.org/details/programming-windows-95" rel="noopener noreferrer"&gt;programar para Windows 95, de Petzold&lt;/a&gt;, tenía más de 1000 páginas), y hasta que llegó &lt;a href="https://es.wikipedia.org/wiki/Embarcadero_Delphi" rel="noopener noreferrer"&gt;Delphi&lt;/a&gt;, entonces de Borland, ahora de Embarcadero, se continuaba programando para MS-DOS, y como mucho, se ejecutaba en una ventana de DOS de Windows, llamada "Símbolo de comando" (?). Excepto grandes empresas, claro.&lt;/p&gt;

&lt;p&gt;Pero eso ya es otra historia.&lt;/p&gt;

</description>
      <category>retro</category>
      <category>pc</category>
      <category>dos</category>
      <category>spanish</category>
    </item>
    <item>
      <title>El caso de VIM como editor de textos</title>
      <dc:creator>Baltasar García Perez-Schofield</dc:creator>
      <pubDate>Wed, 24 Jun 2026 08:05:48 +0000</pubDate>
      <link>https://dev.to/baltasarq/el-caso-de-vim-como-editor-de-textos-4oep</link>
      <guid>https://dev.to/baltasarq/el-caso-de-vim-como-editor-de-textos-4oep</guid>
      <description>&lt;p&gt;Puede parecer que no es cierto, pero &lt;a href="https://es.wikipedia.org/wiki/Unix" rel="noopener noreferrer"&gt;Unix&lt;/a&gt; fue creado en 1969. Las herramientas de UNIX fueron apareciendo a medida que surgían las necesidades para trabajar con él. El primer editor de textos fue &lt;a href="https://es.wikipedia.org/wiki/Ed_(Unix)" rel="noopener noreferrer"&gt;ed&lt;/a&gt;, escrito en ensamblador en 1971. Se trataba de una editor de líneas muy parecido a &lt;strong&gt;EDLIN&lt;/strong&gt;, presente en &lt;a href="https://es.wikipedia.org/wiki/MS-DOS" rel="noopener noreferrer"&gt;MS-DOS&lt;/a&gt;, y &lt;strong&gt;ED&lt;/strong&gt;, presente en &lt;a href="https://es.wikipedia.org/wiki/CP/M" rel="noopener noreferrer"&gt;CP/M&lt;/a&gt; (antecesor de MS_DOS).&lt;/p&gt;

&lt;p&gt;En un editor orientado a líneas, nunca se trabaja sobre todo el documento a la vez, sino que se listan (comando &lt;strong&gt;l&lt;/strong&gt;), una serie de líneas, se borran (comando &lt;strong&gt;d&lt;/strong&gt;), o se insertan (comando &lt;strong&gt;i&lt;/strong&gt;). Cuando se quiere que el comando se aplique a varias líneas, se indica el intervalo separado por una coma, y el comando al final. Por ejemplo, &lt;code&gt;2i&lt;/code&gt; insertaría una línea de texto en la actual línea número 2.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; l
1: Esta es la primera línea.
2: Esta es la segunda línea.
3: Esta es la tercera línea.

&amp;gt; 1,2l
1: Esta es la primera línea.
2: Esta es la segunda línea.

&amp;gt; 2i
Esta es una línea insertada entre la primera y la segunda.

&amp;gt; l
1: Esta es la primera línea.
2: Esta es la segunda línea.
3: Esta es una línea insertada entre la primera y la segunda.
4: Esta es la tercera línea.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pero esta entrada ahonda en el editor de textos &lt;a href="https://es.wikipedia.org/wiki/Vi" rel="noopener noreferrer"&gt;&lt;strong&gt;vi&lt;/strong&gt;&lt;/a&gt;, que nació en 1976 (hace unos 50 años, o medio siglo, en el momento de escribir este texto). Tras unos quince años, en 1991, nació &lt;a href="https://es.wikipedia.org/wiki/Vim" rel="noopener noreferrer"&gt;&lt;strong&gt;vim&lt;/strong&gt;&lt;/a&gt;, o &lt;code&gt;Vi IMproved&lt;/code&gt;, una mejora sobre &lt;strong&gt;vi&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vi&lt;/strong&gt; surgió como una interfaz para &lt;strong&gt;Ex&lt;/strong&gt;, un editor orientado a líneas. Al contrario que estos editores, &lt;strong&gt;Vi&lt;/strong&gt; mostraba el texto completo, en toda la pantalla, de manera que era mucho más cómodo que cualquier editor de textos orientado a líneas. Divide su funcionalidad, en cambio, en dos modos: el modo de edición, y el modo de comando. Así, si en cualquier momento se pulsa ESC para salir del modo de edición (si es que se está en este modo), y después se teclea &lt;code&gt;:q&lt;/code&gt; se sale del programa. Si se teclea &lt;code&gt;:q!&lt;/code&gt;, se sale del programa inmediatamente, descartando posibles cambios. Si se teclea &lt;code&gt;:w&lt;/code&gt;, entonces el archivo se escribe a disco. Se pueden combinar comandos, como &lt;code&gt;:wq&lt;/code&gt;, que escribe el texto en disco y sale del programa.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Modo&lt;/th&gt;
&lt;th&gt;Explicación&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Edición&lt;/td&gt;
&lt;td&gt;Cada tecla pulsada es un nuevo carácter en el texto.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Comando&lt;/td&gt;
&lt;td&gt;Las teclas son parte de un comando.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Comando&lt;/th&gt;
&lt;th&gt;Pasa modo&lt;/th&gt;
&lt;th&gt;Explicación&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;i&lt;/td&gt;
&lt;td&gt;Edición&lt;/td&gt;
&lt;td&gt;Insertar texto antes de la posición actual.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;a&lt;/td&gt;
&lt;td&gt;Edición&lt;/td&gt;
&lt;td&gt;Insertar texto tras la posición actual.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESC&lt;/td&gt;
&lt;td&gt;Comando&lt;/td&gt;
&lt;td&gt;Salir del modo de edición.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;h, j, k, l&lt;/td&gt;
&lt;td&gt;Comando&lt;/td&gt;
&lt;td&gt;Mover el cursor por el texto.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;En 1985 surgió &lt;a href="https://es.wikipedia.org/wiki/GNU_Emacs" rel="noopener noreferrer"&gt;&lt;strong&gt;EMACS&lt;/strong&gt;&lt;/a&gt;, otro editor de textos fuertemente basado en &lt;a href="https://es.wikipedia.org/wiki/Lisp" rel="noopener noreferrer"&gt;&lt;strong&gt;LISP&lt;/strong&gt;&lt;/a&gt;(un lenguaje funcional), para su extensión mediante complementos. La extensión por complementos se hizo tan viral que existen un montón de complementos para él, y de hecho, es conocido como un &lt;em&gt;sistema operativo&lt;/em&gt;, en lugar de un simple editor de texto.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vi&lt;/strong&gt; se apuntó a esta posibilidad de extensión por complementos, de forma que también se convirtió en un editor configurable para múltiples lenguajes de programación, y otras funcionalidades. El hecho es que ambos se han convertido en editores de textos extraordinariamente complejos en cuanto a configuración, de forma que el archivo de configuración de &lt;code&gt;.vimrc&lt;/code&gt; se convierte en un activo complejo, que es necesario compartir entre todos los ordenadores en los que se use.&lt;/p&gt;

&lt;p&gt;Durante muchos años, cuando se estilaban las discusiones espúreas, (como por ejemplo, Windows vs Mac), mucha gente con toneladas de tiempo libre se dedicaban a discutir cuál de ambos editores de texto (&lt;strong&gt;Vi&lt;/strong&gt; vs &lt;strong&gt;Emacs&lt;/strong&gt;), era mejor que el otro.&lt;/p&gt;

&lt;p&gt;Aunque parece que &lt;a href="https://commandlinux.com/statistics/ide-and-text-editor-usage-among-linux-developers-vs-code-vim-emacs-stats/" rel="noopener noreferrer"&gt;el uso de Emacs ha ido decreciendo&lt;/a&gt;, con un porcentaje de uso de menos de un 9%, VIM mantiene un uso de casi un 25%. Entre los programadores en UNIX/LINUX, claro. Hoy en día, con más de un 70%, parece que el editor de textos más popular es &lt;strong&gt;Visual Studio Code&lt;/strong&gt;, incluso con un uso indirecto en editores como &lt;strong&gt;Cursor&lt;/strong&gt;, que utilizan el código fuente de &lt;strong&gt;Visual Studio Code&lt;/strong&gt; para crear su propio editor con el soporte para agentes IA.&lt;/p&gt;

&lt;p&gt;Pero siempre me sorprende que todavía haya mucha gente utilizando &lt;strong&gt;Vi&lt;/strong&gt; o &lt;a href="https://en.wikipedia.org/wiki/Vim_%28cleaning_product%29" rel="noopener noreferrer"&gt;&lt;strong&gt;Vim&lt;/strong&gt;&lt;/a&gt;. Por supuesto, con el tiempo, aparecieron "ayudas": además de poder utilizar h, j, k, l para mover el cursor, se mapearon las flechas del cursor, por poner un ejemplo. Y es que, ¿por qué utilizar teclas "normales" para utilizar funciones de edición de texto?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9v1phf1dq2yu2pmyrwbe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9v1phf1dq2yu2pmyrwbe.png" alt="Terminal " width="400" height="300"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La respuesta es realmente muy simple: porque no había otras teclas disponibles. Lo de arriba es un terminal "tonto", no un ordenador completo; es lo que se utilizaba para comunicarse con el ordenador central. Pero es muy moderno para lo que estamos hablando aquí. El terminal se conoce como &lt;a href="https://es.wikipedia.org/wiki/Terminal_(inform%C3%A1tica)" rel="noopener noreferrer"&gt;&lt;em&gt;tty&lt;/em&gt;&lt;/a&gt;, o máquina de escribir en teletipo (&lt;em&gt;teleprinter&lt;/em&gt; o &lt;em&gt;teletypewriter&lt;/em&gt;); y es que era exactamente eso, una máquina de escribir para enviar comandos al ordenador central, y un papel de teletipo para recibir la respuesta. El terminal del que estamos hablando aparece a continuación.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr1avda6iunf8uii3r1at.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fr1avda6iunf8uii3r1at.jpg" alt="Teleprinter" width="799" height="442"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;¿Parece una máquina de escribir? Efectivamente, la máquina de escribir era lo más parecido por aquella época con respecto a un terminal de ordenador. Teclas para las letras del abecedario, otras para los dígitos del 0 al 9, un tabulador, una barra espaciadora, salto de línea, y poco más.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;¿Sabías que la &lt;a href="https://es.wikipedia.org/wiki/Teclado_QWERTY" rel="noopener noreferrer"&gt;distribución de teclado qwerty&lt;/a&gt; no está pensada para poder escribir tan rápido como sea posible? ¡No! Está pensada para que las teclas más comunes estén muy separadas, y así, las primeras máquinas de escribir no se atascaran...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Así que &lt;strong&gt;Vi&lt;/strong&gt; utilizaba estas teclas "comunes", simplemente, porque no había otras. De ahí que existieran varios modos de operación: de otra forma, no sería posible introducir las teclas de comando en el texto.&lt;/p&gt;

&lt;p&gt;Con el tiempo, aparecieron las teclas especiales: las flechas para el cursor, suprimir y borrar, las flechas de modificación como &lt;em&gt;Ctrl&lt;/em&gt; y &lt;em&gt;Alt&lt;/em&gt;, o incluso, &lt;em&gt;Shift&lt;/em&gt; (no, al principio los ordenadores no tenían letras minúsculas). Una vez que aparecen las teclas especiales, editores de texto como &lt;strong&gt;Vi&lt;/strong&gt;, con múltiples modos, símplemente no son necesarios.&lt;/p&gt;

&lt;p&gt;¿Por qué, entonces, &lt;strong&gt;Vi&lt;/strong&gt; ha sobrevivido con tanta popularidad hasta nuestros días? Sin duda, parte de la respuesta es la aparición de innumerables complementos para el editor. El resto, para mi es un misterio. Sobre todo cuando tenemos en cuenta que &lt;strong&gt;Vi&lt;/strong&gt;, con un par de docenas de complementos, es lo mismo que un editor de textos moderno.&lt;/p&gt;

&lt;p&gt;En cualquier caso, si usas &lt;strong&gt;Vi&lt;/strong&gt;, eres un usuario retro, te guste o no, de un programa que tiene sus raíces en los años 70 del siglo pasado.&lt;/p&gt;

</description>
      <category>spanish</category>
      <category>retro</category>
      <category>editor</category>
      <category>unix</category>
    </item>
  </channel>
</rss>
