<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://geeks.ms/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Variable not found en Geeks.ms : vb.net</title><link>http://geeks.ms/blogs/jmaguilar/archive/tags/vb.net/default.aspx</link><description>Etiquetas: vb.net</description><dc:language /><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><item><title>Sintaxis Razor con VB.NET</title><link>http://geeks.ms/blogs/jmaguilar/archive/2011/07/13/sintaxis-razor-con-vb-net.aspx</link><pubDate>Wed, 13 Jul 2011 12:13:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:197693</guid><dc:creator>José M. Aguilar</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/jmaguilar/rsscomments.aspx?PostID=197693</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2011/07/13/sintaxis-razor-con-vb-net.aspx#comments</comments><description>Desde siempre, C# ha sido el lenguaje por excelencia del framework ASP.NET MVC, y por esta raz&amp;oacute;n es bastante dif&amp;iacute;cil encontrar en la web ejemplos escritos en otros lenguajes, como el popular Visual Basic .NET. En el caso concreto de la capa Vista, pr&amp;aacute;cticamente nadie escribe ejemplos utilizando Razor y VB.NET , por lo que los desarrolladores que siguen optando por este lenguage para trabajar sobre ASP.NET MVC (e incluso WebPages) lo tienen m&amp;aacute;s complicado para entender...(&lt;a href="http://geeks.ms/blogs/jmaguilar/archive/2011/07/13/sintaxis-razor-con-vb-net.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://geeks.ms/aggbug.aspx?PostID=197693" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vb.net/default.aspx">vb.net</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/aspnetmvc/default.aspx">aspnetmvc</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/razor/default.aspx">razor</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/webpages/default.aspx">webpages</category></item><item><title>Parámetros opcionales: úsense con precaución</title><link>http://geeks.ms/blogs/jmaguilar/archive/2010/06/15/par-225-metros-opcionales-250-sense-con-precauci-243-n.aspx</link><pubDate>Tue, 15 Jun 2010 21:39:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:178098</guid><dc:creator>José M. Aguilar</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/jmaguilar/rsscomments.aspx?PostID=178098</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2010/06/15/par-225-metros-opcionales-250-sense-con-precauci-243-n.aspx#comments</comments><description>Los par&amp;aacute;metros opcionales son una interesante ayuda que hace tiempo que est&amp;aacute; presente en otros lenguajes como Visual Basic .NET, y ha sido introducida en la versi&amp;oacute;n 4.0 de C#, para alegr&amp;iacute;a de muchos. A grandes rasgos, esta caracter&amp;iacute;stica nos permite especificar valores por defecto para los par&amp;aacute;metros de nuestros m&amp;eacute;todos, ahorr&amp;aacute;ndonos tiempo de codificaci&amp;oacute;n: class Program { public static void Main( string [] args) { Muestra(); // Imprime...(&lt;a href="http://geeks.ms/blogs/jmaguilar/archive/2010/06/15/par-225-metros-opcionales-250-sense-con-precauci-243-n.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://geeks.ms/aggbug.aspx?PostID=178098" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/desarrollo/default.aspx">desarrollo</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/c_2300_/default.aspx">c#</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/.net/default.aspx">.net</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vb.net/default.aspx">vb.net</category></item><item><title>¿Esa enumeración está vacía?</title><link>http://geeks.ms/blogs/jmaguilar/archive/2010/05/20/191-esa-enumeraci-243-n-est-225-vac-237-a.aspx</link><pubDate>Thu, 20 May 2010 21:33:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:176944</guid><dc:creator>José M. Aguilar</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/jmaguilar/rsscomments.aspx?PostID=176944</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2010/05/20/191-esa-enumeraci-243-n-est-225-vac-237-a.aspx#comments</comments><description>Casualmente encuentro en el post de Chris Eargle &amp;ldquo; Any() versus Count() &amp;rdquo; un tema del que pensaba escribir hace tiempo y al final dej&amp;eacute; en el tintero: &amp;iquest;c&amp;oacute;mo podemos determinar si una enumeraci&amp;oacute;n est&amp;aacute; vac&amp;iacute;a? Vale, es bien f&amp;aacute;cil, una enumeraci&amp;oacute;n est&amp;aacute; vac&amp;iacute;a si tiene cero elementos . Si trabajamos con un array, podemos consultar la propiedad Length ; si se trata de una colecci&amp;oacute;n, podemos utilizar la propiedad Count...(&lt;a href="http://geeks.ms/blogs/jmaguilar/archive/2010/05/20/191-esa-enumeraci-243-n-est-225-vac-237-a.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://geeks.ms/aggbug.aspx?PostID=176944" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/desarrollo/default.aspx">desarrollo</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/c_2300_/default.aspx">c#</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/trucos/default.aspx">trucos</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/.net/default.aspx">.net</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/buenas+pr_26002300_225_3B00_cticas/default.aspx">buenas pr&amp;#225;cticas</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vb.net/default.aspx">vb.net</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/linq/default.aspx">linq</category></item><item><title>Plataforma pro-salvación de Visual Basic .NET (SVB.Net)</title><link>http://geeks.ms/blogs/jmaguilar/archive/2008/12/28/plataforma-pro-salvaci-243-n-de-visual-basic-net-svb-net.aspx</link><pubDate>Sun, 28 Dec 2008 00:01:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:135895</guid><dc:creator>José M. Aguilar</dc:creator><slash:comments>17</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/jmaguilar/rsscomments.aspx?PostID=135895</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2008/12/28/plataforma-pro-salvaci-243-n-de-visual-basic-net-svb-net.aspx#comments</comments><description>&lt;div style="DISPLAY:block;"&gt;&lt;img id="BLOGGER_PHOTO_ID_5282226964123443906" style="FLOAT:right;MARGIN:0px 0px 10px 10px;" alt="Charla de Matt Gretz sobre el futuro de VB.NET" src="http://1.bp.blogspot.com/_O9D62hXq-ng/SU49b_uRYsI/AAAAAAAAA-E/XYURY6wwzb0/s400/the-end-of-vbnet-.jpg" border="0" /&gt;Tras algunos días de intenso debate, ayer quedó constituida SVB.Net, la plataforma pro-salvación de Visual Basic, como movimiento independiente de la comunidad de desarrolladores de habla hispana &lt;a title="Aupa.net, la comunidad de desarrolladores de habla hispana" href="http://aupa.net/"&gt;aupa.net&lt;/a&gt;, cuyo objetivo es apoyar la continuidad del lenguaje y hacer presión para forzar un replanteamiento de su estrategia comercial. &lt;br /&gt;&lt;br /&gt;Para el que todavía no esté al tanto de la historia, durante la segunda semana de diciembre ha tenido lugar en Dallas el encuentro de desarrolladores &lt;a title="Microsoft Events" href="http://www.microsoft.com/events"&gt;DevConn4&lt;/a&gt;, en el que &lt;a title="Posts de Matt Gretz en el blog del VBTeam" href="http://blogs.msdn.com/vbteam/archive/tags/Matt+Gertz/default.aspx"&gt;Matt Gretz&lt;/a&gt;, destacado miembro del equipo de VB.NET, hacía público el Roadmap que Microsoft tiene previsto para este producto, que no trae buenas noticias para la gran comunidad de desarrolladores en Visual Basic, y que provocó un &lt;a title="Death of VB, más de 3 millones de referencias en Google" href="http://www.google.es/search?q=death%20of%20vb"&gt;revuelo impresionante&lt;/a&gt; tanto en la sala del evento como en la blogosfera y medios especializados. &lt;br /&gt;&lt;br /&gt;Resumidamente, el Roadmap prevé la &lt;strong&gt;progresiva desaparición de Visual Basic&lt;/strong&gt;, mediante un plan de migración que facilitará los desarrolladores pasar a C# en un plazo de tres años. A partir de 2012 no se publicarán nuevas versiones de VB, por lo que, dado que el lenguaje no evolucionará para reflejar los cambios que sean introducidos a nivel de framework, lo llevará irremediablemente a su desaparición en no más de cinco años. &lt;br /&gt;&lt;br /&gt;En líneas generales, el contexto actual y el panorama que nos espera, si nadie lo impide, es el siguiente: &lt;/div&gt;
&lt;div style="DISPLAY:block;"&gt;
&lt;ul&gt;
&lt;li&gt;Primero, durante años se han ido introduciendo mejoras en Visual Basic .NET hasta cubrir la mayoría de características del framework e igualarlo en potencia a C#, con objeto de hacer más suave el salto de un lenguaje a otro. Por ejemplo, la inclusión en el actual VB.NET 9 de tal cantidad de novedades y cambios respecto a versiones anteriores, responden claramente a estas necesidades. &lt;br /&gt;&lt;br /&gt;Hasta aquí, todo es correcto y aporta exclusivamente ventajas. El problema viene ahora...&lt;br /&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;La segunda gran acción podremos verla con el próximo Visual Studio 2010 y .Net 4.0, de los cuales ya &lt;a title="Descargar VS2010 CTP" href="http://www.microsoft.com/downloads/details.aspx?familyid=922b4655-93d0-4476-bda4-94cf5f8d4814&amp;amp;displaylang=en"&gt;es posible descargar previews&lt;/a&gt;. Para entonces, &lt;strong&gt;Visual Basic aparecerá con el nombre comercial VB#&lt;/strong&gt; (&lt;em&gt;VB Sharp&lt;/em&gt;), dando a entender que se trata de una versión de transición a C#, y en el que podremos encontrar el giro hacia una sintaxis más cercana a este lenguaje, como el uso de llaves en bloques (&lt;code&gt;if&lt;/code&gt;, blucles &lt;code&gt;while&lt;/code&gt; y &lt;code&gt;for&lt;/code&gt;, etc.), estructuras compactas (como la sintaxis lambda o declaraciones menos verbosas), comentarios tipo C &amp;quot;/*&amp;quot;, y otras lindezas que seguro que dejarán nuestro código VB bastante diferente al actual. Eso sí, para facilitarnos la vida, será el propio IDE el que nos ayude a acostumbrarnos a las particularidades sintácticas, sustituyendo sobre la marcha el código VB.NET tradicional por VB#. &lt;br /&gt;&lt;br /&gt;En esta fase también encontraremos los cambios que se van a producir en C# para dotarlo de algunas de las ventajas de Visual Basic, como los &lt;a title="ElBruno: Parámetros opcionales en C# 4.0" href="http://geeks.ms/blogs/elbruno/archive/2008/12/14/vsts2010-par-225-metros-opcionales-en-c-4-0.aspx"&gt;parámetros opcionales&lt;/a&gt;, con objeto de lograr una mayor confluencia y hacer más fácil la adopción del lenguaje por esta comunidad de desarrolladores.&lt;br /&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;La última parte del plan se llevará a cabo en 2012 con Visual Studio (codename &lt;em&gt;Moonwalker&lt;/em&gt;), que se distribuirá con .NET framework 5.0 (aka &lt;em&gt;Greengarden&lt;/em&gt;) y &lt;strong&gt;no vendrá acompañado de una nueva versión de Visual Basic, sino de un asistente de migración a C#&lt;/strong&gt;. Para esas fechas, además, se prevé que la mayoría de desarrolladores de Visual Basic haya adoptado VB#, por lo que el salto será, en palabras de Matt, &amp;quot;no traumático&amp;quot;.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;
&lt;p&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_O9D62hXq-ng/SU45DUKlcBI/AAAAAAAAA98/caxU8uifZZU/s1600-h/vbnet-roadmap.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5282222142067666962" style="DISPLAY:block;MARGIN:0px auto 10px;WIDTH:389px;CURSOR:hand;HEIGHT:310px;TEXT-ALIGN:center;" alt="Roadmap de VB.NET presentado en DevConn4" src="http://3.bp.blogspot.com/_O9D62hXq-ng/SU45DUKlcBI/AAAAAAAAA98/caxU8uifZZU/s400/vbnet-roadmap.jpg" border="0" /&gt;&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;Finalmente, comentar que también hemos acordado el emblema de la plataforma pro-salvación de Visual Basic que podemos ir utilizando en nuestras páginas para dar difusión al movimiento hasta que tengamos lista la &lt;a href="http://www.svb,net/"&gt;web oficial&lt;/a&gt;, que se prevé finalizada para primeros de año. &lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5281919444101027442" style="FLOAT:right;MARGIN:0px 0px 10px 10px;" alt="Logo Plataforma pro-salvación de Visual Basic" src="http://1.bp.blogspot.com/_O9D62hXq-ng/SU0lv-Xe1nI/AAAAAAAAA9s/POyEGzvckNo/s400/plataforma-pro-vb.jpg" border="0" /&gt;Si eres simpatizante de la causa, programas o has programado en alguna versión de Visual Basic, y tienes blog o una página relacionada con el desarrollo, descárgate esta imagen (¡por favor, no hagas &lt;a title="Qué es el hotlinking" href="http://www.emezeta.com/articulos/hotlinking-enlazando-con-estilo"&gt;hotlinking&lt;/a&gt;!) y colócala en un lugar visible apuntando al futuro sitio web de la plataforma. Si el diseño no encaja en tu web, no te preocupes: en breve tendremos a nuestra disposición nuevos botones en tamaños menores (125 y 250 píxeles de ancho) y con ciertas variaciones estéticas y nuevos colores, e incluso versiones en Flash y Silverlight, según &lt;a title="Blog de Raúl Mondo" href="http://www.raulmondolirondo.net/"&gt;Raúl Mondo&lt;/a&gt;, el diseñador que está realizando este excelente trabajo. &lt;br /&gt;&lt;br /&gt;Y no olvides que cuanto más difundamos esta iniciativa, más fuerza tendremos ante la multinacional para hacer que se replantee su estrategia. &lt;br /&gt;&lt;br /&gt;¡Larga vida a VB.NET! &lt;/p&gt;
&lt;div style="BORDER-RIGHT:black 1px solid;PADDING-RIGHT:3px;BORDER-TOP:black 1px solid;PADDING-LEFT:3px;PADDING-BOTTOM:3px;BORDER-LEFT:black 1px solid;COLOR:black;PADDING-TOP:3px;BORDER-BOTTOM:black 1px solid;BACKGROUND-COLOR:yellow;"&gt;&lt;strong&gt;[Actualizado 29/12]&lt;/strong&gt;&lt;br /&gt;Obviamente la noticia no es real, se trata simplemente de una broma del Día de los Inocentes, pero en cualquier caso... ¡Larga vida a VB! :-D&lt;/div&gt;
&lt;p&gt;Publicado en: &lt;a href="http://www.variablenotfound.com/"&gt;http://www.variablenotfound.com/&lt;/a&gt;.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=135895" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/desarrollo/default.aspx">desarrollo</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/programaci_26002300_243_3B00_n/default.aspx">programaci&amp;#243;n</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/inocentadas/default.aspx">inocentadas</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vb.net/default.aspx">vb.net</category></item><item><title>Métodos genéricos en VB.NET</title><link>http://geeks.ms/blogs/jmaguilar/archive/2008/12/08/m-233-todos-gen-233-ricos-en-vb-net.aspx</link><pubDate>Mon, 08 Dec 2008 22:20:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:126136</guid><dc:creator>José M. Aguilar</dc:creator><slash:comments>4</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/jmaguilar/rsscomments.aspx?PostID=126136</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2008/12/08/m-233-todos-gen-233-ricos-en-vb-net.aspx#comments</comments><description>&lt;p&gt;&lt;img id="BLOGGER_PHOTO_ID_5268937046840719218" style="FLOAT:right;MARGIN:0px 0px 10px 10px;" alt="Código fuente" src="http://3.bp.blogspot.com/_O9D62hXq-ng/SR8GU_zWN3I/AAAAAAAAA8E/dQp4Yu4NE-Y/s400/lupacodigo.png" border="0" /&gt;Al escribir el post &amp;quot;&lt;a title="Métodos genéricos en C#" href="http://www.variablenotfound.com/2008/11/mtodos-genricos-en-c.html"&gt;&lt;font color="#35537a"&gt;Métodos genéricos en C#&lt;/font&gt;&lt;/a&gt;&amp;quot;, estuve pensando en tratar este tema también en VB.NET de forma simultánea, pero al final preferí limitarme a C# para no hacer la entrada más extensa de lo que ya iba a resultar de por sí.&lt;br /&gt;&lt;br /&gt;Esto, unido a un &lt;a title="&amp;#39;Soy desarrollador de VB.NET ¿tenemos algo parecido en VB?&amp;#39;" href="http://www.variablenotfound.com/2008/11/mtodos-genricos-en-c.html?showComment=1227098700000#c3040627247945286538"&gt;&lt;font color="#35537a"&gt;comentario de Julio&lt;/font&gt;&lt;/a&gt; sobre el propio post en el que preguntaba si existía algo parecido en Visual Basic .NET, ha hecho que reedite el mismo, pero centrándome esta vez en dicho lenguaje. &lt;br /&gt;&lt;br /&gt;Los métodos genéricos son interesantes herramientas que están con nosotros desde los tiempos del .NET Framework 2.0 y pueden resultarnos muy útiles de cara a la construcción de frameworks o librerías reutilizables.&lt;br /&gt;&lt;br /&gt;Podríamos considerar que un método genérico es a un método tradicional lo que una &lt;a title="Colabora .NET: Implementando Generics en VB.NET  " href="http://www.mundoprogramacion.com/colabora/NET2006/horacio_generics_vbnet.htm"&gt;&lt;font color="#35537a"&gt;clase genérica&lt;/font&gt;&lt;/a&gt; a una tradicional; por tanto, se trata de un mecanismo de definición de métodos con tipos parametrizados, que nos ofrece la potencia del tipado fuerte en sus parámetros y devoluciones aun sin conocer los tipos concretos que utilizaremos al invocarlos.&lt;br /&gt;&lt;br /&gt;Vamos a profundizar en el tema desarrollando un ejemplo, a través del cual podremos comprender por qué los métodos genéricos pueden sernos muy útiles para solucionar determinado tipo de problemas, y describiremos ciertos aspectos, como las restricciones o la inferencia, que nos ayudarán a sacarles mucho jugo.&lt;br /&gt;&lt;br /&gt;
&lt;h3&gt;Escenario de partida&lt;/h3&gt;
&lt;p&gt;Como sabemos, los métodos tradicionales trabajan con parámetros y retornos fuertemente tipados, es decir, en todo momento conocemos los tipos concretos de los argumentos que recibimos y de los valores que devolvemos. Por ejemplo, en el siguiente código, vemos que el método &lt;code&gt;Maximo&lt;/code&gt;, cuya misión es obvia, recibe dos valores &lt;code&gt;Integer&lt;/code&gt; y retorna un valor del mismo tipo:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  Function Maximo(ByVal uno As &lt;span style="COLOR:blue;"&gt;Integer&lt;/span&gt;, ByVal otro As &lt;span style="COLOR:blue;"&gt;Integer&lt;/span&gt;) _&lt;br /&gt;                  As &lt;span style="COLOR:blue;"&gt;Integer&lt;/span&gt;&lt;br /&gt;    If uno &amp;gt; otro Then Return uno&lt;br /&gt;    Return otro&lt;br /&gt;  End Function&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Hasta ahí, todo correcto. Sin embargo, está claro que retornar el máximo de dos valores es una operación que podría ser aplicada a más tipos, prácticamente a todos los que pudieran ser comparados. Si quisiéramos generalizar este método y hacerlo accesible para otros tipos, se nos podrían ocurrir al menos dos formas de hacerlo.&lt;br /&gt;&lt;br /&gt;La primera sería realizar un buen puñado de sobrecargas del método para intentar cubrir todos los casos que se nos puedan dar:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  Function Maximo(ByVal uno As &lt;span style="COLOR:blue;"&gt;Integer&lt;/span&gt;, ByVal otro As &lt;span style="COLOR:blue;"&gt;Integer&lt;/span&gt;) _&lt;br /&gt;                  As &lt;span style="COLOR:blue;"&gt;Integer&lt;/span&gt;&lt;br /&gt;    &lt;span style="COLOR:green;"&gt;&amp;#39; ...&lt;/span&gt;  &lt;br /&gt;  End Function&lt;br /&gt;  Function Maximo(ByVal uno As &lt;span style="COLOR:blue;"&gt;Long&lt;/span&gt;, ByVal otro As &lt;span style="COLOR:blue;"&gt;Long&lt;/span&gt;) _&lt;br /&gt;                  As &lt;span style="COLOR:blue;"&gt;Long&lt;/span&gt;&lt;br /&gt;    &lt;span style="COLOR:green;"&gt;&amp;#39; ...&lt;/span&gt;  &lt;br /&gt;  End Function&lt;br /&gt;  Function Maximo(ByVal uno As &lt;span style="COLOR:blue;"&gt;Decimal&lt;/span&gt;, ByVal otro As &lt;span style="COLOR:blue;"&gt;Decimal&lt;/span&gt;) _&lt;br /&gt;                  As &lt;span style="COLOR:blue;"&gt;Decimal&lt;/span&gt;&lt;br /&gt;    &lt;span style="COLOR:green;"&gt;&amp;#39; ...&lt;/span&gt;  &lt;br /&gt;  End Function&lt;br /&gt;&lt;br /&gt;  &lt;span style="COLOR:green;"&gt;&amp;#39; Y así hasta que te aburras...&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Obviamente, sería un trabajo demasiado duro para nosotros, desarrolladores perezosos como somos. Además, según &lt;a title="Ley de Murphy" href="http://es.wikipedia.org/wiki/Ley_de_Murphy"&gt;&lt;font color="#35537a"&gt;Murphy&lt;/font&gt;&lt;/a&gt;, por más sobrecargas que creáramos seguro que siempre nos faltaría al menos una: justo la que vamos a necesitar ;-).&lt;br /&gt;&lt;br /&gt;Otra posibilidad sería intentar generalizar utilizando las propiedades de la herencia. Es decir, si asumimos que tanto los valores de entrada del método como su retorno son del tipo base &lt;code&gt;Object&lt;/code&gt;, aparentemente tendríamos el tema resuelto. Lamentablemente, al finalizar nuestra implementación nos daríamos cuenta de que no es posible hacer comparaciones entre dos &lt;code&gt;Object&lt;/code&gt;&amp;#39;s, por lo que, o bien incluimos en el cuerpo del método código para comprobar que ambos sean comparables (consultando si implementan &lt;a title="IComparable (interfaz), en MSDN" href="http://msdn.microsoft.com/es-es/library/system.icomparable(VS.80).aspx"&gt;&lt;code&gt;&lt;font color="#35537a"&gt;IComparable&lt;/font&gt;&lt;/code&gt;&lt;/a&gt;), o bien elevamos el listón de entrada a nuestro método, así:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  Function Maximo(ByVal uno As &lt;span style="COLOR:blue;"&gt;IComparable&lt;/span&gt;, ByVal otro As &lt;span style="COLOR:blue;"&gt;Object&lt;/span&gt;) As &lt;span style="COLOR:blue;"&gt;Object&lt;/span&gt;&lt;br /&gt;    If uno.CompareTo(otro) &amp;gt; 0 Then Return uno&lt;br /&gt;    Return otro&lt;br /&gt;  End Function&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Pero efectivamente, como ya habréis notado, esto tampoco sería una solución válida para nuestro caso. En primer lugar, el hecho de que ambos parámetros sean &lt;code&gt;Object&lt;/code&gt; o &lt;code&gt;IComparable&lt;/code&gt; no asegura en ningún momento que sean del mismo tipo, por lo que podría invocar el método enviándole, por ejemplo, un &lt;code&gt;String&lt;/code&gt; y un &lt;code&gt;Integer&lt;/code&gt;, lo que provocaría un error en tiempo de ejecución. Y aunque es cierto que podríamos incluir código que comprobara que ambos tipos son compatibles, ¿no tendríais la sensación de estar llevando a tiempo de ejecución problemática de tipado que bien podría solucionarse en compilación?&lt;br /&gt;&lt;/p&gt;
&lt;h3&gt;El método genérico&lt;/h3&gt;
&lt;p&gt;Fijaos que lo que andamos buscando es simplemente alguna forma de representar en el código una idea conceptualmente tan sencilla como: &amp;quot;&lt;em&gt;mi método va a recibir dos objetos de un tipo cualquiera &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;, que implemente &lt;code&gt;IComparable&lt;/code&gt;, y va a retornar el que sea mayor de ellos&lt;/em&gt;&amp;quot;. En este momento es cuando los métodos genéricos acuden en nuestro auxilio, permitiendo definir ese concepto como sigue:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  Function Maximo&lt;span style="BACKGROUND-COLOR:#ffffc0;"&gt;(Of &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt; As IComparable)&lt;/span&gt; _&lt;br /&gt;                 (ByVal uno As &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;, ByVal otro As &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;) As &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;&lt;br /&gt;    If uno.CompareTo(otro) &amp;gt; 0 Then Return uno&lt;br /&gt;    Return otro&lt;br /&gt;  End Function&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;En el código anterior, podemos distinguir una porción de código que aparece resaltada justo después del nombre del método, y antes de comenzar a definir sus parámetros. Es la forma de indicar que &lt;code&gt;Maximo&lt;/code&gt; es un método genérico y operará sobre un tipo cualquiera al que llamaremos &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;, y mediante una restricción estamos indicando que deberá implementar obligatoriamenter el interfaz &lt;code&gt;IComparable&lt;/code&gt; (más adelante trataremos esto en profundidad).&lt;br /&gt;&lt;br /&gt;A continuación, podemos observar que los dos parámetros de entrada son del tipo &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;, así como el retorno de la función. Si no lo ves claro, sustituye mentalmente la letra T por &lt;code&gt;Integer&lt;/code&gt; (por ejemplo) y seguro que mejora la cosa.&lt;br /&gt;&lt;br /&gt;Lógicamente, estos métodos pueden presentar un número indeterminado de parámetros genéricos, como en el siguiente ejemplo. Observad que la palabra clave &lt;code&gt;Of&lt;/code&gt; sólo se indica al principio:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  Function MiMetodo(Of &lt;span style="COLOR:blue;"&gt;T1&lt;/span&gt;, &lt;span style="COLOR:blue;"&gt;T2&lt;/span&gt;, &lt;span style="COLOR:blue;"&gt;TResult&lt;/span&gt;) _&lt;br /&gt;                   (ByVal par1 As &lt;span style="COLOR:blue;"&gt;T1&lt;/span&gt;, ByVal par2 As &lt;span style="COLOR:blue;"&gt;T2&lt;/span&gt;) As &lt;span style="COLOR:blue;"&gt;TResult&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Y una aclaración antes de continuar: lo de usar la letra &lt;code&gt;T&lt;/code&gt; para identificar el tipo es pura convención, podríamos llamarlo de cualquier forma (por ejemplo &lt;code&gt;Maximo(Of MiTipo)(ByVal uno as MiTipo, ByVal otro as MiTipo) As MiTipo&lt;/code&gt;), aunque ceñirse a las convenciones de codificación es normalmente una buena idea.&lt;br /&gt;&lt;/p&gt;
&lt;h3&gt;Restricciones en parámetros genéricos&lt;/h3&gt;
&lt;p&gt;Retomemos un momento el código de nuestro método genérico:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  Function Maximo(Of &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt; As IComparable) _&lt;br /&gt;                 (ByVal uno As &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;, ByVal otro As &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;) As &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;&lt;br /&gt;    If uno.CompareTo(otro) &amp;gt; 0 Then Return uno&lt;br /&gt;    Return otro&lt;br /&gt;  End Function&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Antes había comentado que en este caso estabamos creando un método que podría actuar sobre cualquier tipo, aunque mediante una restricción forzábamos a que éste implementara, obligatoriamente, el interfaz &lt;code&gt;IComparable&lt;/code&gt;, lo que nos permitiría realizar la operación de comparación que necesitamos.&lt;br /&gt;&lt;br /&gt;Obviamente, las restricciones no son obligatorias; de hecho, sólo debemos utilizarlas cuando necesitemos limitar de alguna forma los tipos permitidos como parámetros genéricos, como en el ejemplo anterior. Está permitida la utilización de las siguientes reglas: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;As Structure&lt;/code&gt;, indica que el argumento debe ser un tipo valor. 
&lt;li&gt;&lt;code&gt;As Class&lt;/code&gt;, indica que T debe ser un tipo referencia. 
&lt;li&gt;&lt;code&gt;As New&lt;/code&gt;, fuerza a que el tipo T disponga de un constructor público sin parámetros; es útil cuando desde dentro del método se pretende instanciar un objeto del mismo. 
&lt;li&gt;&lt;code&gt;As &lt;em&gt;nombredeclase&lt;/em&gt;&lt;/code&gt;, indica que el argumento debe heredar o ser de dicho tipo. 
&lt;li&gt;&lt;code&gt;As &lt;em&gt;nombredeinterfaz&lt;/em&gt;&lt;/code&gt;, el argumento deberá implementar el interfaz indicado. 
&lt;li&gt;&lt;code&gt;As &lt;em&gt;nombredetipogenérico&lt;/em&gt;&lt;/code&gt;, indica que el argumento al que se aplica debe ser igual o heredar del tipo, también argumento del método, indicado por &lt;em&gt;nombredetipogenérico&lt;/em&gt; (observad en el siguiente ejemplo el parámetro T2).&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Un último detalle relativo a esto: a un mismo parámetro se pueden aplicar varias restricciones, en cuyo caso se introducirán entre llaves (&amp;quot;{&amp;quot; y &amp;quot;}&amp;quot;) separadas por comas, como aparece en el siguiente ejemplo:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  Function MiMetodo(Of &lt;span style="COLOR:blue;"&gt;T1&lt;/span&gt; As {Class, IEnumerable}, _&lt;br /&gt;                       &lt;span style="COLOR:blue;"&gt;T2&lt;/span&gt; As {&lt;span style="COLOR:blue;"&gt;T1&lt;/span&gt;, New}, _&lt;br /&gt;                       &lt;span style="COLOR:blue;"&gt;TResult&lt;/span&gt; As New) _&lt;br /&gt;                   (ByVal par1 As &lt;span style="COLOR:blue;"&gt;T1&lt;/span&gt;, ByVal par2 As &lt;span style="COLOR:blue;"&gt;T2&lt;/span&gt;) As &lt;span style="COLOR:blue;"&gt;TResult&lt;/span&gt;&lt;br /&gt;    &lt;span style="COLOR:green;"&gt;&amp;#39; ... Cuerpo del método&lt;/span&gt;&lt;br /&gt;  End Function&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Uso de métodos genéricos&lt;/h3&gt;
&lt;p&gt;A estas alturas ya sabemos, más o menos, cómo se define un método genérico, pero nos falta aún conocer cómo podemos consumirlos, es decir, invocarlos desde nuestras aplicaciones. Aunque puede intuirse, la llamada a los métodos genéricos debe incluir tanto la tradicional lista de parámetros del método como los tipos que lo concretan. Vemos unos ejemplos:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  Dim mazinger As String = Maximo(Of String)(&amp;quot;Mazinger&amp;quot;, &amp;quot;Afrodita&amp;quot;)&lt;br /&gt;  Dim i99 As Integer = Maximo(Of Integer)(2, 99)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Una interesantísima característica de la invocación de estos métodos es la capacidad del compilador para inferir, en muchos casos, los tipos que debe utilizar como parámetros genéricos, evitándonos tener que indicarlos de forma expresa. El siguiente código, totalmente equivalente al anterior, aprovecha esta característica:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  Dim mazinger As String = Maximo(&amp;quot;Mazinger&amp;quot;, &amp;quot;Afrodita&amp;quot;)&lt;br /&gt;  Dim i99 As Integer = Maximo(2, 99)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;El compilador deduce el tipo del método genérico a partir de los que estamos utilizando en la lista de parámetros. Por ejemplo, en el primer caso, dado que los dos parámetros son &lt;code&gt;String&lt;/code&gt;, puede llegar a la conclusión de que el método tiene una signatura que coincide con la definición del genérico, utilizando &lt;code&gt;String&lt;/code&gt; como tipo parametrizado.&lt;br /&gt;&lt;/p&gt;
&lt;h3&gt;Otro ejemplo de método genérico&lt;/h3&gt;
&lt;p&gt;Veamos un ejemplo un poco más complejo. El método &lt;code&gt;CreaLista&lt;/code&gt;, aplicable a cualquier clase, retorna una lista genérica (&lt;code&gt;List(Of T)&lt;/code&gt;) del tipo parametrizado del método, que rellena inicialmente con los argumentos (variables) que se le suministra:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  Function CreaLista(Of &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;)(ByVal ParamArray pars() As &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;) As List(Of &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;)&lt;br /&gt;    Dim list As New List(Of &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;)&lt;br /&gt;    For Each elem As &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt; In pars&lt;br /&gt;      list.Add(elem)&lt;br /&gt;    Next&lt;br /&gt;    Return list&lt;br /&gt;  End Function&lt;br /&gt;&lt;br /&gt;  &lt;span style="COLOR:green;"&gt;&amp;#39; ...&lt;br /&gt;  &amp;#39; Uso:&lt;/span&gt;&lt;br /&gt;  Dim nums = CreaLista(Of &lt;span style="COLOR:blue;"&gt;Integer&lt;/span&gt;)(1, 2, 3, 4, 5, 6, 7)&lt;br /&gt;  Dim noms = CreaLista(Of &lt;span style="COLOR:blue;"&gt;String&lt;/span&gt;)(&amp;quot;Pepe&amp;quot;, &amp;quot;Juan&amp;quot;, &amp;quot;Luis&amp;quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Otros ejemplos de uso, ahora beneficiándonos de la inferencia de tipos:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  Dim nums = CreaLista(1, 2, 3, 4, 5, 6, 7)&lt;br /&gt;  Dim noms = CreaLista(&amp;quot;Pepe&amp;quot;, &amp;quot;Juan&amp;quot;, &amp;quot;Luis&amp;quot;)&lt;br /&gt;&lt;br /&gt;  &lt;span style="COLOR:green;"&gt;&amp;#39; Incluso con tipos anónimos de VB.NET 9&lt;/span&gt;&lt;br /&gt;  Dim v = CreaLista( _&lt;br /&gt;                     New With {.X = 1, .Y = 2}, _&lt;br /&gt;                     New With {.X = 3, .Y = 4} _&lt;br /&gt;                   )&lt;br /&gt;  Console.WriteLine(v(1).Y) &lt;span style="COLOR:green;"&gt;&amp;#39; Muestra &amp;quot;4&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;En resumen, se trata de una característica de la plataforma .NET, reflejada en lenguajes como C# y VB.Net, que está siendo ampliamente utilizada en las últimas incorporaciones al framework, y a la que hay que habituarse para poder trabajar eficientemente con ellas.&lt;br /&gt;&lt;br /&gt;Publicado en: &lt;a href="http://www.variablenotfound.com/"&gt;&lt;font color="#35537a"&gt;www.variablenotfound.com&lt;/font&gt;&lt;/a&gt;. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=126136" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/desarrollo/default.aspx">desarrollo</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/programaci_26002300_243_3B00_n/default.aspx">programaci&amp;#243;n</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/.net/default.aspx">.net</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vs2008/default.aspx">vs2008</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vb.net/default.aspx">vb.net</category></item><item><title>Atajo para instanciar tipos anónimos en C# y VB.NET</title><link>http://geeks.ms/blogs/jmaguilar/archive/2008/11/02/atajo-para-instanciar-tipos-an-243-nimos-en-c-y-vb-net.aspx</link><pubDate>Sun, 02 Nov 2008 22:59:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:110518</guid><dc:creator>José M. Aguilar</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/jmaguilar/rsscomments.aspx?PostID=110518</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2008/11/02/atajo-para-instanciar-tipos-an-243-nimos-en-c-y-vb-net.aspx#comments</comments><description>&lt;p&gt;&lt;img id="BLOGGER_PHOTO_ID_5257782992821215410" style="BORDER-RIGHT:black 1px solid;BORDER-TOP:black 1px solid;FLOAT:right;MARGIN:0px 0px 10px 10px;BORDER-LEFT:black 1px solid;WIDTH:150px;BORDER-BOTTOM:black 1px solid;" alt="" src="http://2.bp.blogspot.com/_O9D62hXq-ng/SPdlxmky4LI/AAAAAAAAA6A/dcKogD7SW8U/s320/phpcode.jpg" border="0" /&gt;Tanto la guía de programación del lenguaje &lt;a title="Tipos anónimos (Guía de programación de C#)" href="http://msdn.microsoft.com/es-es/library/bb397696.aspx"&gt;&lt;font color="#35537a"&gt;C# 3.0&lt;/font&gt;&lt;/a&gt; como la de &lt;a title="Deducir tipos y nombres de propiedades en declaraciones de tipos anónimos" href="http://msdn.microsoft.com/es-es/library/bb531357.aspx"&gt;&lt;font color="#35537a"&gt;Visual Basic .NET 9&lt;/font&gt;&lt;/a&gt; hablan de que ambos compiladores pueden agilizar la instanciación de tipos anónimos, permitiendo escribir instrucciones realmente concisas, gracias a su capacidad para deducir los nombres de las propiedades a partir de su contexto. Sin embargo son ese tipo de detalles que, al menos un servidor, había pasado por alto a pesar de haberlo visto utilizado más de una vez.&lt;br /&gt;&lt;br /&gt;Como sabemos, la creación &amp;quot;normal&amp;quot; de un objeto de tipo anónimo es como sigue, si lo que queremos es inicializar sus propiedades con valores constantes:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  &lt;span style="COLOR:green;"&gt;// C#&lt;/span&gt;&lt;br /&gt;  var o = new { Nombre=&amp;quot;Juan&amp;quot;, Edad=23 };&lt;br /&gt;&lt;br /&gt;  &lt;span style="COLOR:green;"&gt;&amp;#39; VB.NET&lt;/span&gt;&lt;br /&gt;  Dim o = New With { .Nombre=&amp;quot;Juan&amp;quot;, .Edad=23 }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Sin embargo, muchas veces vamos a inicializar sus miembros con valores tomados de variables o parámetros visibles en el lugar de la instanciación, por ejemplo:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  &lt;span style="COLOR:green;"&gt;// C#&lt;/span&gt;&lt;br /&gt;  public void hacerAlgo(string nombre, int edad)&lt;br /&gt;  {&lt;br /&gt;    &lt;strong&gt;var o = new { nombre=nombre, edad=edad };&lt;/strong&gt;&lt;br /&gt;    ...&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style="COLOR:green;"&gt;&amp;#39; VB.NET&lt;/span&gt;&lt;br /&gt;  Public Sub HacerAlgo(ByVal nombre As String, _&lt;br /&gt;                       ByVal edad As Integer)&lt;br /&gt;    &lt;strong&gt;Dim o = New With {.nombre = nombre, .edad = edad}&lt;/strong&gt;&lt;br /&gt;    ... &lt;br /&gt;  End Sub&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Pues bien, es justo en estos casos cuando podemos utilizar una sintaxis más compacta, basada en la capacidad de los compiladores de inferir el nombre de las propiedades del tipo anónimo partiendo de los identificadores de las variables que utilicemos en su inicialización. O en otras palabras, el siguiente código es equivalente al anterior:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  &lt;span style="COLOR:green;"&gt;// C#&lt;/span&gt;&lt;br /&gt;  public void hacerAlgo(string nombre, int edad)&lt;br /&gt;  {&lt;br /&gt;    &lt;strong&gt;var o = new { nombre, edad };&lt;/strong&gt;&lt;br /&gt;    ...&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style="COLOR:green;"&gt;&amp;#39; VB.NET&lt;/span&gt;&lt;br /&gt;  Public Sub HacerAlgo(ByVal nombre As String, _&lt;br /&gt;                       ByVal edad As Integer)&lt;br /&gt;    &lt;strong&gt;Dim o = New With {nombre, edad}&lt;/strong&gt;&lt;br /&gt;    ... &lt;br /&gt;  End Sub&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bradwilson.typepad.com/blog/2008/10/c-anonymous-object-tip.html"&gt;&lt;font color="#35537a"&gt;Brad Wilson&lt;/font&gt;&lt;/a&gt;, un desarrollador del equipo ASP.NET de Microsoft, nos ha recordado hace unos días lo bien que viene este atajo para la instanciación de tipos anónimos utilizados para almacenar &lt;a title="Using anonymous types as dictionaries" href="http://weblogs.asp.net/leftslipper/archive/2007/09/24/using-c-3-0-anonymous-types-as-dictionaries.aspx"&gt;diccionarios clave/valor&lt;/a&gt;, como los usados en el framework ASP.NET MVC. También es una característica muy utilizada en Linq para el retorno de tipos anónimos que contienen un subconjunto de propiedades de las entidades recuperadas en una consulta.&lt;br /&gt;&lt;br /&gt;Publicado en: &lt;a href="http://www.variablenotfound.com/"&gt;&lt;font color="#35537a"&gt;www.variablenotfound.com&lt;/font&gt;&lt;/a&gt;. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=110518" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/c_2300_/default.aspx">c#</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/trucos/default.aspx">trucos</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/.net/default.aspx">.net</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vs2008/default.aspx">vs2008</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vb.net/default.aspx">vb.net</category></item><item><title>Cómo describir los elementos de una enumeración usando métodos de extensión y atributos (C# y VB.NET)</title><link>http://geeks.ms/blogs/jmaguilar/archive/2008/05/06/c-243-mo-describir-los-elementos-de-una-enumeraci-243-n-usando-m-233-todos-de-extensi-243-n-y-atributos-c-y-vb-net.aspx</link><pubDate>Tue, 06 May 2008 17:13:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:84930</guid><dc:creator>José M. Aguilar</dc:creator><slash:comments>5</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/jmaguilar/rsscomments.aspx?PostID=84930</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2008/05/06/c-243-mo-describir-los-elementos-de-una-enumeraci-243-n-usando-m-233-todos-de-extensi-243-n-y-atributos-c-y-vb-net.aspx#comments</comments><description>&lt;p&gt;&lt;img id="BLOGGER_PHOTO_ID_5170639638121466338" style="FLOAT:right;MARGIN:0px 0px 10px 10px;CURSOR:hand;" alt="" src="http://bp2.blogger.com/_O9D62hXq-ng/R8HNWwvIyeI/AAAAAAAAARg/bri51ZijKvk/s320/cscode.png" border="0" /&gt;Me he encontrado en el blog de &lt;a title="[ING] Enum Values With User Defined Strings, Made Easy" href="http://blogs.freshlogicstudios.com/Posts/View.aspx?Id=388f7d39-0b90-43bc-b03a-c1f605dfb499"&gt;&lt;font color="#35537a"&gt;Fresh Logic Studios&lt;/font&gt;&lt;/a&gt; con un post donde describen una técnica interesante para obtener descripciones textuales de los elementos de una enumeración. De hecho, ya la había visto hace tiempo en &lt;a title="[ING] C# 3.0: using extension methods for enum ToString" href="http://blogs.msdn.com/abhinaba/archive/2005/10/21/483337.aspx"&gt;&lt;font color="#35537a"&gt;I know the answer&lt;/font&gt;&lt;/a&gt; como una aplicación de los métodos de extensión para mejorar una solución que aportaba en un &lt;a title="[ING] C#: Enum and overriding ToString on it" href="http://blogs.msdn.com/abhinaba/archive/2005/10/20/483000.aspx"&gt;&lt;font color="#35537a"&gt;post anterior&lt;/font&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Como sabemos, si desde una aplicación queremos obtener una descripción comprensible de un elemento de una enumeración, normalmente no podemos realizar una conversión directa (&lt;code&gt;elemento.ToString()&lt;/code&gt;) del mismo, pues obtenemos los nombres de los identificadores usados a nivel de código. La solución habitual, hasta la llegada de C# 3.0 consistía en incluir dentro de alguna clase de utilidad un conversor estático que recibiera como parámetro en elemento de la enumeración y retornara un string, algo así como:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;        &lt;br /&gt;  public static string EstadoProyecto2String(EstadoProyecto e)&lt;br /&gt;  {&lt;br /&gt;    switch (e)&lt;br /&gt;    {&lt;br /&gt;      case EstadoProyecto.PendienteDeAceptacion:&lt;br /&gt;        return &amp;quot;Pendiente de aceptación&amp;quot;;&lt;br /&gt;      case EstadoProyecto.EnRealizacion:&lt;br /&gt;        return &amp;quot;En realización&amp;quot;;&lt;br /&gt;      case EstadoProyecto.Finalizado:&lt;br /&gt;        return &amp;quot;Finalizado&amp;quot;;&lt;br /&gt;      default:&lt;br /&gt;        throw &lt;br /&gt;          new ArgumentOutOfRangeException(&amp;quot;Error: &amp;quot; + e);&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Este método, sin embargo, presenta algunos inconvenientes. En primer lugar, dado el tipado fuerte del parámetro de entrada del método, es necesario crear una función similar para cada enumeración sobre la que queramos realizar la operación. &lt;br /&gt;&lt;br /&gt;También puede resultar peligroso separar la definición de la enumeración del método que transforma sus elementos a cadena de caracteres, puesto que puede perderse la sincronización entre ambos cuando, por ejemplo, se introduzca un nuevo elemento en ella y no se actualice el método con la descripción asociada.&lt;br /&gt;&lt;br /&gt;La solución, que como he comentado me pareció muy interesante, consiste en decorar cada elemento de la enumeración con un atributo que describa al mismo, e implementar un método de extensión sobre la clase base &lt;code&gt;System.Enum&lt;/code&gt; para obtener estos valores. Veamos cómo.&lt;br /&gt;&lt;br /&gt;Ah, una cosa más. Aunque los ejemplos están escritos en C#, se puede conseguir exactamente el mismo resultado en VB.NET simplemente realizando las correspondientes adaptaciones sintácticas. Podrás encontrarlo al final del post.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3&gt;1. Declaración de la enumeración&lt;/h3&gt;
&lt;p&gt;Vamos a usar el atributo &lt;code&gt;System.ComponentModel.DescriptionAttribute&lt;/code&gt;, aunque podríamos usar cualquier otro que nos interese, o incluso &lt;a title="Crear atributos personalizados en MSDN" href="http://msdn.microsoft.com/es-es/library/84c42s56(VS.80).aspx"&gt;&lt;font color="#35537a"&gt;crear nuestro propio atributo personalizado&lt;/font&gt;&lt;/a&gt;. El código de definición de la enumeración sería así:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  using System.ComponentModel;&lt;br /&gt;&lt;br /&gt;  public enum EstadoProyecto&lt;br /&gt;  {&lt;br /&gt;    [Description(&amp;quot;Pendiente de aceptación&amp;quot;)] PendienteDeAceptacion,&lt;br /&gt;    [Description(&amp;quot;En realización&amp;quot;)]          EnRealizacion,&lt;br /&gt;    [Description(&amp;quot;Finalizado&amp;quot;)]              Finalizado,&lt;br /&gt;    [Description(&amp;quot;Facturado y cerrado&amp;quot;)]     FacturadoYCerrado&lt;br /&gt;  }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;2. Implementación del método de extensión&lt;/h3&gt;
&lt;p&gt;Ahora vamos a crear el método de extensión (&lt;a title="Métodos de extensión" href="http://www.variablenotfound.com/2008/02/mtodos-de-extensin-en-c.html"&gt;&lt;font color="#35537a"&gt;¿qué son los métodos de extensión?&lt;/font&gt;&lt;/a&gt;) que se aplicará a todas las enumeraciones.&lt;br /&gt;&lt;br /&gt;Fijaos que el parámetro de entrada del método está precedido por la palabra reservada &lt;code&gt;this&lt;/code&gt; y el tipo es &lt;code&gt;System.Enum&lt;/code&gt;, por lo que será aplicable a cualquier enumeración.&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;using System;&lt;br /&gt;using System.ComponentModel;&lt;br /&gt;using System.Reflection;&lt;br /&gt;&lt;br /&gt;public static class Utils&lt;br /&gt;{&lt;br /&gt;  public static string GetDescription(this Enum e)&lt;br /&gt;  {&lt;br /&gt;    FieldInfo field = e.GetType().GetField(e.ToString());&lt;br /&gt;    if (field != null)&lt;br /&gt;    {&lt;br /&gt;      object[] attribs = &lt;br /&gt;        field.GetCustomAttributes(typeof(DescriptionAttribute), false);&lt;br /&gt;&lt;br /&gt;      if (attribs.Length &amp;gt; 0)&lt;br /&gt;        return (attribs[0] as DescriptionAttribute).Description;&lt;br /&gt;    }&lt;br /&gt;    return e.ToString();&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bp1.blogger.com/_O9D62hXq-ng/SB4BuK2h3vI/AAAAAAAAAbQ/P3Zo-5Fthr4/s1600-h/EnumWithExtensionMethods.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5196592912730808050" style="FLOAT:right;MARGIN:0px 0px 10px 10px;CURSOR:hand;" alt="" src="http://bp1.blogger.com/_O9D62hXq-ng/SB4BuK2h3vI/AAAAAAAAAbQ/P3Zo-5Fthr4/s400/EnumWithExtensionMethods.png" border="0" /&gt;&lt;/a&gt;Y voila! A partir de este momento tendremos a nuestra disposición el método &lt;code&gt;GetDescription()&lt;/code&gt;, que nos devolverá el texto asociado al elemento de la enumeración; si éste no existe, es decir, si no se ha decorado el elemento con el atributo apropiado, nos devolverá el identificador utilizado.&lt;br /&gt;&lt;br /&gt;De esta forma eliminamos de un plumazo los dos inconvenientes citados anteriormente: la separación entre la definición de la enumeración y los textos descriptivos, y la necesidad de crear un conversor a texto por cada enumeración que usemos en nuestra aplicación.&lt;br /&gt;&lt;br /&gt;Y por cierto, el equivalente en VB.NET completo sería:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;Imports System.ComponentModel&lt;br /&gt;Imports System.Reflection&lt;br /&gt;Imports System.Runtime.CompilerServices&lt;br /&gt;&lt;br /&gt;Module Module1&lt;br /&gt;    Public Enum EstadoProyecto&lt;br /&gt;        &amp;lt;Description(&amp;quot;Pendiente de aceptación&amp;quot;)&amp;gt; PendienteDeAceptacion&lt;br /&gt;        &amp;lt;Description(&amp;quot;En realización&amp;quot;)&amp;gt; EnRealizacion&lt;br /&gt;        &amp;lt;Description(&amp;quot;Finalizado&amp;quot;)&amp;gt; Finalizado&lt;br /&gt;        &amp;lt;Description(&amp;quot;Facturado y cerrado&amp;quot;)&amp;gt; FacturadoYCerrado&lt;br /&gt;    End Enum&lt;br /&gt;&lt;br /&gt;    &amp;lt;Extension()&amp;gt; _&lt;br /&gt;    Public Function GetDescription(ByVal e As System.Enum) As String&lt;br /&gt;        Dim field As FieldInfo = e.GetType().GetField(e.ToString())&lt;br /&gt;        If Not (field Is Nothing) Then&lt;br /&gt;            Dim attribs() As Object = _&lt;br /&gt;                field.GetCustomAttributes(GetType(DescriptionAttribute), False)&lt;br /&gt;            If attribs.Length &amp;gt; 0 Then&lt;br /&gt;                Return CType(attribs(0), DescriptionAttribute).Description&lt;br /&gt;            End If&lt;br /&gt;        End If&lt;br /&gt;        Return e.ToString()&lt;br /&gt;    End Function&lt;br /&gt;End Module&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Publicado en: &lt;a href="http://www.variablenotfound.com/"&gt;&lt;font color="#35537a"&gt;www.variablenotfound.com&lt;/font&gt;&lt;/a&gt;. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=84930" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/programaci_26002300_243_3B00_n/default.aspx">programaci&amp;#243;n</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/c_2300_/default.aspx">c#</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/trucos/default.aspx">trucos</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/.net/default.aspx">.net</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vb.net/default.aspx">vb.net</category></item><item><title>Efectos laterales en métodos parciales</title><link>http://geeks.ms/blogs/jmaguilar/archive/2008/04/16/efectos-laterales-en-m-233-todos-parciales.aspx</link><pubDate>Wed, 16 Apr 2008 19:04:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:83245</guid><dc:creator>José M. Aguilar</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/jmaguilar/rsscomments.aspx?PostID=83245</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2008/04/16/efectos-laterales-en-m-233-todos-parciales.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://bp1.blogger.com/_O9D62hXq-ng/R_u3ACDcDaI/AAAAAAAAAUw/8Uhf_ka6jtc/s1600-h/sorprendido.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5186940607026433442" style="FLOAT:right;MARGIN:0px 0px 10px 10px;CURSOR:hand;" alt="¡Sorpresa!" src="http://bp1.blogger.com/_O9D62hXq-ng/R_u3ACDcDaI/AAAAAAAAAUw/8Uhf_ka6jtc/s320/sorprendido.jpg" border="0" /&gt;&lt;/a&gt;Hace unos días comentaba que el uso de &lt;a title="Métodos parciales en C# y VB.Net" href="http://www.variablenotfound.com/2008/04/mtodos-parciales-en-c-3-y-vbnet-9.html"&gt;&lt;font color="#35537a"&gt;métodos parciales&lt;/font&gt;&lt;/a&gt; puede causar algunos problemas en la ejecución de nuestras aplicaciones que podríamos calificar, cuanto menos, de &amp;quot;incómodos&amp;quot;.&lt;br /&gt;&lt;br /&gt;Recordemos que una parte de una clase parcial puede declarar un método y utilizarlo (invocarlo) dentro de su código; si el método está implementado en otro fragmento de la clase, se ejecutará como siempre, pero si no ha sido implementado, &lt;em&gt;el compilador eliminará tanto la declaración del método como las llamadas que se hagan al mismo&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;Sin embargo esta eliminación pueden causar efectos no deseados difíciles de detectar.&lt;br /&gt;&lt;br /&gt;Veámoslo con un ejemplo. Supongamos una clase parcial como la siguiente, que representa a una variable de tipo entero que puede ser incrementada o decrementada a través de métodos:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt; public partial class Variable&lt;br /&gt; {&lt;br /&gt;   &lt;strong&gt;partial void Log(string msg);&lt;/strong&gt;&lt;br /&gt;   private int i = 0;&lt;br /&gt;&lt;br /&gt;   public void Inc()&lt;br /&gt;   {&lt;br /&gt;      i++;&lt;br /&gt;      &lt;strong&gt;Log(&amp;quot;Incremento. I: &amp;quot; + i);&lt;/strong&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public void Dec()&lt;br /&gt;   {&lt;br /&gt;      &lt;strong&gt;Log(&amp;quot;Decremento. I: &amp;quot; + (--i));&lt;/strong&gt;&lt;br /&gt;   }&lt;br /&gt;&lt;br /&gt;   public int Value&lt;br /&gt;   {&lt;br /&gt;     get { return i; }&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Creamos ahora un código que utiliza esta clase de forma muy simple: crea una variable, la incrementa dos veces, la decrementa una vez y muestra el resultado:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt; Variable v = new Variable();&lt;br /&gt; v.Inc();&lt;br /&gt; v.Inc();&lt;br /&gt; v.Dec();&lt;br /&gt; Console.WriteLine(v.Value);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Obviamente, tras la ejecución de este código la pantalla mostrará por consola un &amp;quot;1&amp;quot;, ¿no? Claro, el resultado de realizar dos incrementos y un decremento sobre el cero.&lt;br /&gt;&lt;br /&gt;Pues no necesariamente. De hecho, es imposible conocer, a la vista del código mostrado hasta ahora, cuál será el resultado mostrado por consola al finalizar la ejecución. Dependiendo de la existencia de la implementación del método parcial &lt;code&gt;Log()&lt;/code&gt;, declarado e invocado en la clase &lt;code&gt;Variable&lt;/code&gt; anterior, puede ocurrir:&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Si existe otra porción de la misma clase (otra &lt;code&gt;partial class Variable&lt;/code&gt;) donde se implemente el método, se ejecutará éste. El valor mostrado por consola, salvo que desde esta implementación se modificara el valor del campo privado, sería &amp;quot;1&amp;quot;.&lt;br /&gt;&lt;br /&gt;
&lt;li&gt;Si no existe una implementación del método &lt;code&gt;Log()&lt;/code&gt; en la clase, el compilador &lt;em&gt;eliminará&lt;/em&gt; todas las llamadas al mismo. Pero si observáis, esto incluye el decremento del valor interno, que estaba en el interior de la llamada como un autodecremento:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;Log(&amp;quot;Decremento. I: &amp;quot; + &lt;strong&gt;(--i)&lt;/strong&gt;);&lt;/code&gt;&lt;/pre&gt;Por tanto, en este caso, el compilador eliminará tanto la llamada a &lt;code&gt;Log()&lt;/code&gt; como la operación que se realiza en el interior. Obviamente, el resultado de ejecución de la prueba anterior sería &amp;quot;2&amp;quot;. &lt;br /&gt;&lt;br /&gt;Lo mismo ocurriría si el resultado a mostrar fuera el valor de retorno de una llamada a otra función: esta no se ejecutaría, lo cual puede ser grave si en ella se realiza una operación importante, como por ejemplo:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;public function InicializaValores()&lt;br /&gt;{&lt;br /&gt;   Log(&amp;quot;Elementos reestablecidos: &amp;quot; + reseteaElementos() );&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Conclusión: usad los métodos parciales siempre con precaución, pues podemos introducir errores muy difíciles de detectar y corregir, sobre todo por falta aparente de relación entre causa y efecto. &lt;br /&gt;&lt;br /&gt;Por ejemplo, imaginad que el ejemplo anterior contiene una implementación de &lt;code&gt;Log()&lt;/code&gt;; la aplicación funcionaría correctamente. Sin embargo, si pasado un tiempo se decide eliminar esta implementación (por ejemplo, porque ya no es necesario registrar las operaciones realizadas), la operación de decremento (&lt;code&gt;Dec()&lt;/code&gt;) dejaría de funcionar. &lt;br /&gt;&lt;br /&gt;Aunque, eso sí, no es nada que no se pueda solucionar con un buen juego de pruebas...&lt;br /&gt;&lt;br /&gt;Publicado en: &lt;a href="http://www.variablenotfound.com/"&gt;&lt;font color="#35537a"&gt;http://www.variablenotfound.com/&lt;/font&gt;&lt;/a&gt;. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=83245" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/programaci_26002300_243_3B00_n/default.aspx">programaci&amp;#243;n</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/c_2300_/default.aspx">c#</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/trucos/default.aspx">trucos</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/.net/default.aspx">.net</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vs2008/default.aspx">vs2008</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vb.net/default.aspx">vb.net</category></item><item><title>Métodos parciales en C# 3 y VB.NET 9</title><link>http://geeks.ms/blogs/jmaguilar/archive/2008/04/13/m-233-todos-parciales-en-c-3-y-vb-net-9.aspx</link><pubDate>Sun, 13 Apr 2008 19:13:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:83036</guid><dc:creator>José M. Aguilar</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/jmaguilar/rsscomments.aspx?PostID=83036</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2008/04/13/m-233-todos-parciales-en-c-3-y-vb-net-9.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://bp3.blogger.com/_O9D62hXq-ng/R-KyJyDcDSI/AAAAAAAAATw/Gfz7uODxBoI/s1600-h/puzzle.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5179898402554252578" style="FLOAT:right;MARGIN:0px 0px 10px 10px;CURSOR:hand;" alt="Piezas de puzzle" src="http://bp3.blogger.com/_O9D62hXq-ng/R-KyJyDcDSI/AAAAAAAAATw/Gfz7uODxBoI/s200/puzzle.png" border="0" /&gt;&lt;/a&gt;Una vez visto el concepto de las &lt;a href="http://www.variablenotfound.com/2008/04/clases-parciales-en-c-y-vbnet.html"&gt;&lt;font color="#35537a"&gt;clases parciales&lt;/font&gt;&lt;/a&gt;, ya es posible profundizar en los métodos parciales, una característica aparecida en las nuevas versiones de los lenguajes estrella de Microsoft, C# y VB.Net.&lt;br /&gt;&lt;br /&gt;Estos métodos, declarados en el contexto de una clase parcial, permiten comunicar de forma segura los distintos fragmentos de dicha clase. De forma similar a los eventos, permiten que un código incluya una llamada a una función que puede (o no) haber sido implementada por un código cliente, aunque en este caso obligatoriamente la implementación se encontrará en uno de los fragmentos de la misma clase desde donde se realiza la llamada.&lt;br /&gt;&lt;br /&gt;En la práctica significa que una clase parcial puede declarar un método y utilizarlo (invocarlo) dentro de su código; si el método está implementado en otro fragmento de la clase, se ejecutará como siempre, pero si no ha sido implementado, el código correspondiente a la llamada será eliminado en tiempo compilación para optimizar el resultado... &lt;em&gt;¡sí, eliminado!&lt;/em&gt;&lt;br /&gt;&lt;br /&gt;Por ejemplo, el siguiente código muestra una declaración de un método parcial en el interior de una clase, y su utilización desde dentro de uno de sus métodos:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt; &lt;span style="COLOR:green;"&gt;// C#&lt;/span&gt;&lt;br /&gt; public partial class Ejemplo&lt;br /&gt; {&lt;br /&gt;   &lt;strong&gt;   &lt;br /&gt;   &lt;span style="COLOR:green;"&gt;// El método parcial se declara&lt;br /&gt;   // sin implementación...&lt;/span&gt;&lt;br /&gt;   partial void Log(string msg);&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;   public void RealizarAlgo()&lt;br /&gt;   {&lt;br /&gt;     hacerAlgoComplejo();&lt;br /&gt;     &lt;strong&gt;Log(&amp;quot;¡Ojo!&amp;quot;); &lt;span style="COLOR:green;"&gt;// Usamos el método&lt;br /&gt;                   // parcial declarado antes&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;   }&lt;br /&gt;   &lt;br /&gt;   [...] &lt;span style="COLOR:green;"&gt;// Otros métodos y propiedades&lt;/span&gt;&lt;br /&gt;&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; &lt;span style="COLOR:green;"&gt;&amp;#39; VB.NET&lt;/span&gt;&lt;br /&gt; Partial Public Class Ejemplo&lt;br /&gt;&lt;br /&gt;   &lt;strong&gt;&lt;span style="COLOR:green;"&gt;&amp;#39; El método parcial se declara, sin&lt;br /&gt;   &amp;#39; implementar nada en el cuerpo&lt;/span&gt;&lt;br /&gt;   Partial Private Sub Log(ByVal msg As String)&lt;br /&gt;   End Sub&lt;/strong&gt;&lt;br /&gt;&lt;br /&gt;  Public Sub RealizarAlgo()&lt;br /&gt;    HacerAlgoComplejo()&lt;br /&gt;    &lt;strong&gt;Log(&amp;quot;¡Ojo!&amp;quot;) &lt;span style="COLOR:green;"&gt;&amp;#39; Usamos el método parcial&lt;/span&gt;&lt;/strong&gt;&lt;br /&gt;  End Sub&lt;br /&gt;&lt;br /&gt;  [...] &lt;span style="COLOR:green;"&gt;&amp;#39; Otros métodos y propiedades&lt;/span&gt;&lt;br /&gt; End Class&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Y esta la parte realmente curiosa. Cuando el compilador detecta la invocación del método parcial &lt;code&gt;Log()&lt;/code&gt;, buscará en todos los fragmentos de la clase a ver si existe una implementación del mismo. Si no existe, eliminará del ensamblado resultante la llamada a dichos métodos, es decir, &lt;em&gt;actuará como si éstas no existieran en el código fuente&lt;/em&gt;.&lt;br /&gt;&lt;br /&gt;En caso afirmativo, es decir, si existen implementaciones como las del siguiente ejemplo, todo se ejecutará conforme a lo previsto:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt; &lt;span style="COLOR:green;"&gt;// C#&lt;/span&gt;&lt;br /&gt; public partial class Variable&lt;br /&gt; {&lt;br /&gt;   partial void Log(string msg)&lt;br /&gt;   {&lt;br /&gt;     Console.WriteLine(msg);&lt;br /&gt;   }&lt;br /&gt; }&lt;br /&gt;&lt;br /&gt; &lt;span style="COLOR:green;"&gt;&amp;#39; VB.Net&lt;/span&gt;&lt;br /&gt; Partial Public Class Variable&lt;br /&gt;   Private Sub Log(ByVal msg As String)&lt;br /&gt;     Console.WriteLine(msg)&lt;br /&gt;   End Sub&lt;br /&gt; End Class&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Antes comentaba que los métodos parciales son, en cierto sentido, similares a los eventos, pues conceptualmente permiten lo mismo: pasar el control a un código cliente en un momento dado, en el caso de que éste exista. De hecho, hay muchos desarrolladores que lo consideran como un sustituto ligero a los eventos, pues permite prácticamente lo mismo pero se implementan de forma más sencilla. &lt;br /&gt;&lt;br /&gt;Existen, sin embargo, algunas diferencias entre ambos modelos, como:&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Los métodos parciales se implementan en la propia clase, mientras que los eventos pueden ser consumidos también desde cualquier otra 
&lt;li&gt;El enlace, o la suscripción, a eventos es dinámica, se realiza en tiempo de ejecución, es necesario incluir código para ello; los métodos parciales, sin embargo, se vinculan en tiempo de compilación 
&lt;li&gt;Los eventos permiten múltiples suscripciones, es decir, asociarles más de un código cliente 
&lt;li&gt;Los eventos pueden presentar cualquier visibilidad (pública, privada...), mientras que los métodos parciales son obligatoriamente privados.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;También puede verse como algo parecido a la herencia en una jerarquía de clases. Una clase puede incluir un método virtual vacío y utilizarlo en su implementación, y si una clase hija sobreescribe el mismo, ésta se ejecutará en su lugar. Pero claro, hay que tener en cuenta que el ámbito de consumo del método parcial es la misma clase donde se declara e implementa.&lt;br /&gt;&lt;br /&gt;Por último, es conveniente citar algunas consideraciones sobre los métodos parciales:&lt;br /&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Deben ser siempre privados (ya lo había comentado antes) 
&lt;li&gt;No deben devolver valores (en VB.Net serían &lt;code&gt;SUB&lt;/code&gt;, en C# serían de tipo &lt;code&gt;void&lt;/code&gt;) 
&lt;li&gt;Pueden ser estáticos (shared en VB) 
&lt;li&gt;Pueden usar parámetros, acceder a los miembros privados de la clase... en definitiva, actuar como un método más de la misma&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;br /&gt;En resumen, los métodos parciales forman parte del conjunto de novedades de C# y VB.Net que no son absolutamente necesarias y que a veces pueden parecer incluso diabólicas, pues facilitan la dispersión de código y dificultan la legibilidad. Además, en breve publicaré un post comentando posibles efectos laterales a tener en cuenta cuando usemos los métodos parciales en nuestros desarrollos.&lt;br /&gt;&lt;br /&gt;Sin embargo, es innegable que los métodos parciales nos facilitan enormemente la inclusión de código de usuario en el interior de clases generadas de forma automática. Por ejemplo, el diseñador visual del modelo de datos de LinqToSQL genera los &lt;code&gt;DataContext&lt;/code&gt; como clases parciales, en las que define un método parcial llamado &lt;code&gt;OnCreated()&lt;/code&gt;. Si el usuario quiere incluir alguna inicialización personal al crear los DataContext, no tendrá que tocar el código generado de forma automática; simplemente creará otro fragmento de la clase parcial e implementará este método, de una forma mucho más natural y cómoda que si se tratara de un evento.&lt;br /&gt;&lt;br /&gt;Publicado en: &lt;a href="http://www.variablenotfound.com/"&gt;&lt;font color="#35537a"&gt;http://www.variablenotfound.com/&lt;/font&gt;&lt;/a&gt;. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=83036" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/desarrollo/default.aspx">desarrollo</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/programaci_26002300_243_3B00_n/default.aspx">programaci&amp;#243;n</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/c_2300_/default.aspx">c#</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/.net/default.aspx">.net</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vs2008/default.aspx">vs2008</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vb.net/default.aspx">vb.net</category></item><item><title>Clases parciales en C# y VB.NET</title><link>http://geeks.ms/blogs/jmaguilar/archive/2008/04/02/clases-parciales-en-c-y-vb-net.aspx</link><pubDate>Wed, 02 Apr 2008 19:32:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:82259</guid><dc:creator>José M. Aguilar</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/jmaguilar/rsscomments.aspx?PostID=82259</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2008/04/02/clases-parciales-en-c-y-vb-net.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://bp3.blogger.com/_O9D62hXq-ng/R-KyJyDcDSI/AAAAAAAAATw/Gfz7uODxBoI/s1600-h/puzzle.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5179898402554252578" style="FLOAT:right;MARGIN:0px 0px 10px 10px;CURSOR:hand;" alt="Piezas de puzzle" src="http://bp3.blogger.com/_O9D62hXq-ng/R-KyJyDcDSI/AAAAAAAAATw/Gfz7uODxBoI/s200/puzzle.png" border="0" /&gt;&lt;/a&gt;Aunque las clases parciales aparecieron hace unos años, con la llegada de .Net 2.0 y Visual Studio 2005, vamos a hacer un breve repaso como preparación para un próximo post que trate los métodos parciales.&lt;br /&gt;&lt;br /&gt;Las clases parciales (llamados también tipos parciales) son una característica presente en algunos lenguajes de programación, como C# y VB.Net, que permiten que la declaración de una clase se realice en varios archivos de código fuente, rompiendo así la tradicional regla &amp;quot;una clase, un archivo&amp;quot;. Será tarea del compilador tomar las porciones de los distintos archivos y fundirlas en una única entidad.&lt;br /&gt;&lt;br /&gt;En VB.Net y C#, a diferencia de otros lenguajes, es necesario indicar explícitamente que una clase es parcial, es decir, que es posible que haya otros archivos donde se continúe la declaración de la misma, usando en ambos con la palabra clave &lt;code&gt;partial&lt;/code&gt; en la definición del tipo:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  &lt;span style="COLOR:green;"&gt;&amp;#39; VB.NET &lt;/span&gt;&lt;br /&gt;  Public Partial Class Persona&lt;br /&gt;    ...&lt;br /&gt;  End Class&lt;br /&gt;&lt;br /&gt;  &lt;span style="COLOR:green;"&gt;// C#&lt;/span&gt;&lt;br /&gt;  public partial class Persona&lt;br /&gt;  {&lt;br /&gt;    ...&lt;br /&gt;  }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;En este código hemos visto cómo se declara una clase parcial en ambos lenguajes, que es prácticamente idéntica salvo por los detalles sintácticos obvios. Por ello, a partir de este momento continuaré introduciendo los ejemplos sólo en C#.&lt;br /&gt;&lt;br /&gt;Pero antes un inciso: la única diferencia entre ambos, estrictamente hablando, es que C# obliga a que todas las apariciones de la clase estén marcadas como parciales, mientras que en VB.Net puede dejarse una de ellas (llamémosla &amp;quot;declaración principal&amp;quot;) sin indicar que es parcial, y especificarlo en el resto de apariciones. En mi opinión, esta no es una práctica recomendable, por lo que aconsejaría utilizar el modificador &lt;code&gt;partial&lt;/code&gt; siempre que la clase lo sea, e independientemente del lenguaje utilizado, pues contribuirá a la mantenibilidad del código.&lt;br /&gt;&lt;br /&gt;El número de partes en las que se divide una clase es indiferente, el compilador tomará todas ellas y generará en el ensamblado como si fuera una clase normal.&lt;br /&gt;&lt;br /&gt;Para comprobarlo he creado un pequeño código con dos clases exactamente iguales, salvo en su nombre. Una de ellas se denomina &lt;code&gt;PersonaTotal&lt;/code&gt;, y está definida como siempre, en un único archivo; la otra, &lt;code&gt;PersonaParcial&lt;/code&gt;, es parcial y la he troceado en tres archivos, como sigue:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  &lt;span style="COLOR:green;"&gt;// &lt;strong&gt;*** Archivo PersonaParcial.Propiedades.cs ***&lt;/strong&gt;&lt;br /&gt;  // Aquí definiremos todas las propiedades&lt;/span&gt;&lt;br /&gt;  partial class PersonaParcial&lt;br /&gt;  {&lt;br /&gt;    public string Nombre { get; set; }&lt;br /&gt;    public string Apellidos { get; set; }&lt;br /&gt;  }&lt;br /&gt; &lt;br /&gt;  &lt;span style="COLOR:green;"&gt;// &lt;strong&gt;*** Archivo PersonaParcial.IEnumerable.cs ***&lt;/strong&gt;&lt;br /&gt;  // Aquí implementaremos el interfaz IEnumerable&lt;/span&gt;&lt;br /&gt;  partial class PersonaParcial: IEnumerable&lt;br /&gt;  {&lt;br /&gt;    public IEnumerator GetEnumerator()&lt;br /&gt;    {&lt;br /&gt;      throw new NotImplementedException();&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style="COLOR:green;"&gt;// &lt;strong&gt;*** Archivo PersonaParcial.Metodos.cs ***&lt;/strong&gt;&lt;br /&gt;  // Aquí implementaremos los métodos que necesitemos&lt;/span&gt;&lt;br /&gt;  partial class PersonaParcial&lt;br /&gt;  {&lt;br /&gt;    public override string ToString()&lt;br /&gt;    {&lt;br /&gt;      return Nombre + &amp;quot; &amp;quot; + Apellidos;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;/pre&gt;
&lt;p&gt;&lt;/code&gt;&lt;font face="Trebuchet MS"&gt;Y efectivamente, el resultado de compilar ambas clases, según se puede observar con ILDASM es idéntico:&lt;br /&gt;&lt;br /&gt;&lt;/font&gt;&lt;a href="http://bp2.blogger.com/_O9D62hXq-ng/R-KqxiDcDRI/AAAAAAAAATo/WWMfV3zLsgQ/s1600-h/clasesparciales.png"&gt;&lt;font face="Trebuchet MS"&gt;&lt;img id="BLOGGER_PHOTO_ID_5179890289361030418" style="DISPLAY:block;MARGIN:0px auto 10px;CURSOR:hand;TEXT-ALIGN:center;" alt="Clases generadas tras la compilación" src="http://bp2.blogger.com/_O9D62hXq-ng/R-KqxiDcDRI/AAAAAAAAATo/WWMfV3zLsgQ/s400/clasesparciales.png" border="0" /&gt;&lt;/font&gt;&lt;/a&gt;&lt;br /&gt;&lt;font face="Trebuchet MS"&gt;A la hora de crear clases parciales es conveniente tener los siguientes aspectos en cuenta: &lt;/font&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Los atributos de la clase resultante serán la combinación de los atributos definidos en cada una de las partes. 
&lt;li&gt;El tipo base de los distintos fragmentos debe ser el mismo, o aparecer sólo en una de las declaraciones parciales. 
&lt;li&gt;Si se trata de una &lt;a href="http://www.variablenotfound.com/2007/03/generics-en-c.html"&gt;&lt;font color="#35537a"&gt;clase genérica&lt;/font&gt;&lt;/a&gt;, los parámetros deben coincidir en todas las partes. 
&lt;li&gt;Los interfaces que implemente la clase resultante será la unión de todos los implementados por las distintas secciones. 
&lt;li&gt;De la misma forma, los miembros (métodos, propiedades, campos...) de la clase final será la unión de todos los definidos en las distintas partes.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Vale, ya hemos visto qué son y cómo se usan, pero, ¿para qué sirven? ¿cuándo es conveniente utilizarlas? Pues bien, son varios los motivos de su existencia, algunos discutibles y otros realmente interesantes.&lt;br /&gt;&lt;br /&gt;En primer lugar, no era sencillo que varios desarrolladores trabajaran sobre una misma clase de forma concurrente. Incluso utilizando sistemas de control de versiones (como &lt;a href="http://es.wikipedia.org/wiki/Microsoft_Visual_SourceSafe"&gt;&lt;font color="#35537a"&gt;Sourcesafe&lt;/font&gt;&lt;/a&gt; o &lt;a href="http://es.wikipedia.org/wiki/Subversion"&gt;&lt;font color="#35537a"&gt;Subversion&lt;/font&gt;&lt;/a&gt;), la unidad mínima de trabajo es el archivo de código fuente, y la edición simultánea podía generar problemas a la hora de realizar fusiones de las porciones modificadas por cada usuario.&lt;br /&gt;&lt;br /&gt;En segundo lugar, permite que clases realmente extensas puedan ser troceadas para facilitar su comprensión y mantenimiento. Igualmente, puede utilizarse para separar código en base a distintos criterios: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;por ejemplo, separar la interfaz (los miembros visibles desde el exterior de la clase) y por otra los miembros privados a la misma 
&lt;li&gt;o bien separar las porciones que implementan interfaces, o sobreescriben miembros de clases antecesoras de los pertenecientes a la propia clase 
&lt;li&gt;o separar temas concernientes a distintos dominios o aspectos&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;En tercer lugar, aunque da la impresión que fue el motivo más importante para decidir su inclusión, las clases parciales permiten utilizar de forma efectiva herramientas automáticas de generación de código.&lt;br /&gt;&lt;br /&gt;Así, es posible que un desarrollador y un generador estén introduciendo cambios sobre la misma clase sin molestarse, cada uno jugando con su propia porción de la clase; el primero puede introducir funcionalidades sin preocuparse de que una nueva generación automática de código pueda machacar su trabajo. Visual Studio y otros entornos de desarrollo hacen uso intensivo de esta capacidad, por ejemplo, en los diseñadores visuales de Windows Forms, WPF, ASP.Net e incluso el generador de modelos de LinqToSql.&lt;br /&gt;&lt;br /&gt;Publicado en: &lt;a href="http://www.variablenotfound.com/"&gt;&lt;font color="#35537a"&gt;http://www.variablenotfound.com/&lt;/font&gt;&lt;/a&gt;. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=82259" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/desarrollo/default.aspx">desarrollo</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/programaci_26002300_243_3B00_n/default.aspx">programaci&amp;#243;n</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/c_2300_/default.aspx">c#</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/trucos/default.aspx">trucos</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/.net/default.aspx">.net</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vb.net/default.aspx">vb.net</category></item><item><title>Cómo conseguir uniones en .Net</title><link>http://geeks.ms/blogs/jmaguilar/archive/2008/03/09/c-243-mo-conseguir-uniones-en-net.aspx</link><pubDate>Sun, 09 Mar 2008 20:32:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:78946</guid><dc:creator>José M. Aguilar</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/jmaguilar/rsscomments.aspx?PostID=78946</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2008/03/09/c-243-mo-conseguir-uniones-en-net.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://bp2.blogger.com/_O9D62hXq-ng/R9RH6YH7nrI/AAAAAAAAAS4/rM9L4dOn56I/s1600-h/binario.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5175840939989245618" style="FLOAT:right;MARGIN:0px 0px 10px 10px;CURSOR:hand;" alt="" src="http://bp2.blogger.com/_O9D62hXq-ng/R9RH6YH7nrI/AAAAAAAAAS4/rM9L4dOn56I/s320/binario.png" border="0" /&gt;&lt;/a&gt;Hace unos meses hablaba sobre la posibilidad de manipular la forma en la que el framework almacena por defecto la información para obtener &lt;a href="http://www.variablenotfound.com/2007/10/enumeraciones-de-campos-de-bits-en-net.html"&gt;&lt;font color="#35537a"&gt;enumeraciones de campos de bits&lt;/font&gt;&lt;/a&gt;, algo que es muy habitual en programación a bajo nivel. Siguiendo en la misma línea, hoy voy a comentar cómo conseguir uniones en .Net, al más puro estilo C.&lt;br /&gt;&lt;br /&gt;Una unión es muy similar a una estructura de datos (&lt;code&gt;struct&lt;/code&gt; en C# o &lt;code&gt;Structure&lt;/code&gt; en VB.Net), salvo en un detalle: sus componentes se almacenan sobre las mismas posiciones de memoria. O visto desde el ángulo opuesto, una unión podríamos definirla como una porción de memoria donde se guardan varias variables, habitualmente de tipos diferentes. Veamos un ejemplo clásico que nos ayudará a entender el concepto, en un lenguaje cualquiera:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;union Ejemplo&lt;br /&gt;{&lt;br /&gt;  char caracter; // suponiendo char de 8 bits&lt;br /&gt;  byte octeto;   // un byte ocupa 8 bits&lt;br /&gt;};&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Si declaramos una variable x del tipo Ejemplo, estaremos reservando un espacio de 8 bits al que accederemos desde cualquiera de sus miembros, como vemos a continuación:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;    x.caracter = &amp;#39;A&amp;#39;;&lt;br /&gt;    x.octeto ++;&lt;br /&gt;    escribir_char (x.caracter); // mostraría &amp;#39;B&amp;#39;  &lt;br /&gt;    escribir_byte (x.octeto);   // mostraría 66&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Pero espera... ¿memoria?... ¿almacenamiento de variables?... ¿pero existe eso en .Net?... Pues sí, aunque lo más normal es que no nos tengamos que enfrentar nunca a ello pues el framework realiza estas tareas por nosotros, hay escenarios en los que es necesario controlar la forma en que la información es almacenada en memoria, como cuando se esté operando a bajo nivel, por ejemplo creando estructuras específicas para llamar al API de Windows, o para facilitar el acceso a posiciones concretas de la información.&lt;br /&gt;&lt;br /&gt;Desde la versión 1.1 de la plataforma .Net, disponemos del atributo &lt;a href="http://msdn2.microsoft.com/en-us/library/system.runtime.interopservices.structlayoutattribute(VS.71).aspx"&gt;&lt;font color="#35537a"&gt;StructLayout&lt;/font&gt;&lt;/a&gt;, que nos permite indicar en estructuras y clases cómo queremos representar en memoria la información de sus miembros. Básicamente, podemos indicar que:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;la información se almacene como el framework considere oportuno (&lt;code&gt;LayoutKind.Auto&lt;/code&gt;) 
&lt;li&gt;que se almacene de forma secuencial, en el mismo orden en el que han sido declarados (&lt;code&gt;LayoutKind.Sequential&lt;/code&gt;). 
&lt;li&gt;que se almacene donde le indiquemos de forma explícita (&lt;code&gt;LayoutKind.Explicit&lt;/code&gt;). En este caso, necesitaremos especificar en cada miembro la posición exacta de memoria donde será guardado, utilizando el atributo &lt;a href="http://msdn2.microsoft.com/en-us/library/ht8w3dyh(VS.71).aspx"&gt;&lt;code&gt;&lt;font color="#35537a"&gt;FieldOffset&lt;/font&gt;&lt;/code&gt;&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Es este último método el que nos interesa para nuestros propósitos. Si adornamos una estructura con &lt;code&gt;StructLayout(LayoutKind.Explicit)&lt;/code&gt; e indicamos en cada uno de sus miembros su desplazamiento (en bytes) dentro del espacio de memoria asignado a la misma, podemos conseguir uniones haciendo que todos ellos comiencen en la misma dirección.&lt;br /&gt;&lt;br /&gt;Pasemos a vamos a verlo con un ejemplo en C#. Se trata de una unión a la que podemos acceder tratándola como un carácter unicode, o bien como un entero de 16 bits con signo. Los dos miembros, llamados &lt;code&gt;Caracter&lt;/code&gt; y &lt;code&gt;Valor&lt;/code&gt; están definidos sobre la misma posición de memoria (desplazamiento cero) en el interior de la estructura:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;using System.Runtime.InteropServices;&lt;br /&gt;using System;&lt;br /&gt;namespace PruebaUniones&lt;br /&gt;{&lt;br /&gt;     [&lt;strong&gt;StructLayout(LayoutKind.Explicit)&lt;/strong&gt;]&lt;br /&gt;     public struct UnionTest&lt;br /&gt;     {&lt;br /&gt;            [&lt;strong&gt;FieldOffset(0)&lt;/strong&gt;] public char Caracter;&lt;br /&gt;            [&lt;strong&gt;FieldOffset(0)&lt;/strong&gt;] public short Valor;&lt;br /&gt;     }    &lt;br /&gt;    class Program&lt;br /&gt;    {&lt;br /&gt;        public static void Main()&lt;br /&gt;        {&lt;br /&gt;            UnionTest ut = new UnionTest();&lt;br /&gt;            ut.Caracter = &amp;#39;A&amp;#39;;&lt;br /&gt;            ut.Valor ++;&lt;br /&gt;            Console.WriteLine(ut.Caracter); // Muestra &amp;quot;B&amp;quot;&lt;br /&gt;            Console.ReadKey();&lt;br /&gt;            return;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ahora usaremos VB.NET para mostrar otro ejemplo un poco más complejo que el anterior, donde usamos una unión para descomponer una palabra de 16 bits en los dos bytes que la componen, permitiendo la manipulación de forma directa e independiente de cada una de las dos visiones del valor almacenado en memoria. Para el ejemplo utilizo una unión dentro de otra, aunque no era estrictamente necesario, para que veáis que esto es posible.&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;Imports System.Runtime.InteropServices&lt;br /&gt;&lt;br /&gt;&amp;lt;&lt;strong&gt;StructLayout(LayoutKind.Explicit)&lt;/strong&gt;&amp;gt; _&lt;br /&gt;Public Structure Union16&lt;br /&gt;    &amp;lt;&lt;strong&gt;FieldOffset(0)&lt;/strong&gt;&amp;gt; Dim Word As Int16&lt;br /&gt;    &amp;lt;&lt;strong&gt;FieldOffset(0)&lt;/strong&gt;&amp;gt; Dim Bytes As Bytes&lt;br /&gt;End Structure&lt;br /&gt;&lt;br /&gt;&amp;lt;&lt;strong&gt;StructLayout(LayoutKind.Explicit)&lt;/strong&gt;&amp;gt; _&lt;br /&gt;Public Structure Bytes&lt;br /&gt;    &amp;lt;&lt;strong&gt;FieldOffset(0)&lt;/strong&gt;&amp;gt; Dim Bajo As Byte&lt;br /&gt;    &amp;lt;&lt;strong&gt;FieldOffset(1)&lt;/strong&gt;&amp;gt; Dim Alto As Byte&lt;br /&gt;End Structure&lt;br /&gt;&lt;br /&gt;Public Class Program&lt;br /&gt;    Public Shared Sub main()&lt;br /&gt;        Dim u As New Union16&lt;br /&gt;        u.Word = 513         &amp;#39; 513 = 256*1 (Byte alto) + 1 (byte bajo)&lt;br /&gt;        u.Bytes.Alto += 1&lt;br /&gt;        Console.WriteLine(&amp;quot;Word: &amp;quot; &amp;amp; u.Word)            &amp;#39; Muestra 769 (3*256+1)&lt;br /&gt;        Console.WriteLine(&amp;quot;Byte alto: &amp;quot; &amp;amp; u.Bytes.Alto) &amp;#39; Muestra 3&lt;br /&gt;        Console.WriteLine(&amp;quot;Byte bajo: &amp;quot; &amp;amp; u.Bytes.Bajo) &amp;#39; Muestra 1&lt;br /&gt;        Console.ReadKey()&lt;br /&gt;        Console.ReadKey()&lt;br /&gt;    End Sub&lt;br /&gt;End Class&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;He encontrado un uso muy interesante para esta técnica en &lt;a href="http://www.xtremedotnettalk.com/showthread.php?goto=lastpost&amp;amp;t=97390"&gt;&lt;font color="#35537a"&gt;Xtreme .Net Talk&lt;/font&gt;&lt;/a&gt;, donde se muestra un ejemplo de cómo acceder a los componentes de color de un pixel de forma muy eficiente a través de una unión entre el valor ARGB (32 bits) y cada uno de los bytes que lo componen (alfa, rojo, verde y azul). &lt;br /&gt;&lt;br /&gt;En cualquier caso no se recomienda el uso de uniones salvo en casos muy concretos, y siempre conociendo bien las implicaciones que puede tener en la estabilidad y mantenibilidad del sistema.&lt;br /&gt;&lt;br /&gt;Pero bueno, ¡está bien al menos saber que existen!&lt;br /&gt;&lt;br /&gt;Publicado en: &lt;a href="http://www.variablenotfound.com/"&gt;&lt;font color="#35537a"&gt;http://www.variablenotfound.com/&lt;/font&gt;&lt;/a&gt;. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=78946" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/programaci_26002300_243_3B00_n/default.aspx">programaci&amp;#243;n</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/c_2300_/default.aspx">c#</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/.net/default.aspx">.net</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/nivel+alto/default.aspx">nivel alto</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vb.net/default.aspx">vb.net</category></item><item><title>Comentar porciones de código en un archivo .ASPX </title><link>http://geeks.ms/blogs/jmaguilar/archive/2008/03/05/comentar-porciones-de-c-243-digo-en-un-archivo-aspx.aspx</link><pubDate>Wed, 05 Mar 2008 19:50:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:77390</guid><dc:creator>José M. Aguilar</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/jmaguilar/rsscomments.aspx?PostID=77390</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2008/03/05/comentar-porciones-de-c-243-digo-en-un-archivo-aspx.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://bp3.blogger.com/_O9D62hXq-ng/R82C_v8qbRI/AAAAAAAAARw/7o0aTUs7tho/s1600-h/asp.net.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5173935578632842514" style="FLOAT:right;MARGIN:0px 0px 10px 10px;CURSOR:hand;" alt="" src="http://bp3.blogger.com/_O9D62hXq-ng/R82C_v8qbRI/AAAAAAAAARw/7o0aTUs7tho/s320/asp.net.png" border="0" /&gt;&lt;/a&gt;Cuando estamos desarrollando es habitual que tengamos que comentar porciones de código para realizar pruebas. Esto resulta de lo más sencillo cuando programamos en un lenguaje de los habituales como Javascript, C#, Visual Basic o incluso (X)HTML, pues todos ellos disponen de marcadores que hacen que el compilador o intérprete ignore determinadas líneas de código... pero, ¿cómo logramos este efecto si se trata de un archivo .ASPX, donde pueden encontrarse varios de ellos a la vez?&lt;br /&gt;&lt;br /&gt;Por ejemplo, dado el siguiente código en el interior de una página ASP.NET, ¿cuál sería la forma correcta de comentarlo?&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;script&amp;gt;&lt;br /&gt;    var count = &amp;lt;%= borrarRegistros() %&amp;gt;&lt;br /&gt;    alert(&amp;quot;Borrados: &amp;quot; + count + &amp;quot; registros&amp;quot;);&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Una primera opción podría ser utilizar la sintaxis Javascript de la siguiente forma:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;script&amp;gt;&lt;br /&gt;    /*&lt;br /&gt;    var count = &amp;lt;%= borrarRegistros() %&amp;gt;&lt;br /&gt;    alert(&amp;quot;Borrados: &amp;quot; + count + &amp;quot; registros&amp;quot;);&lt;br /&gt;    */&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Sin embargo, aunque podría valer en muchas ocasiones, también puede introducir unos efectos laterales considerables. Nótese que aunque el código Javascript (cliente) esté comentado, la función &lt;code&gt;borrarRegistros()&lt;/code&gt; sería invocada en el lado del servidor, y su retorno introducido dentro del comentario. De hecho, la página enviada a cliente mostraría un código fuente similar al siguiente (imaginando que el retorno de la función fuera el valor 99):&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&amp;lt;script&amp;gt;&lt;br /&gt;    /*&lt;br /&gt;    var count = 99;&lt;br /&gt;    alert(&amp;quot;Borrados: &amp;quot; + count + &amp;quot; registros&amp;quot;);&lt;br /&gt;    */&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Tampoco valdría para nada incluir todo el bloque de script dentro de un comentario HTML (&amp;lt;!-- y --&amp;gt;), por la misma razón que antes. Además, en cualquiera de estos dos casos, estaríamos enviando al cliente la información aunque sea éste el que la ignora a la hora de mostrarla o ejecutarla y, por supuesto, estaríamos ejecutando la función en servidor, lo cual podría causar otros efectos no deseados, como, en nuestro ejemplo, eliminar los registros de una base de datos.&lt;br /&gt;&lt;br /&gt;Afortunadamente, ASP.NET dispone de un mecanismo, denominado &lt;strong&gt;Server Side Comments (comentarios en el lado del servidor)&lt;/strong&gt;, que permite marcar zonas y hacer que se ignore todo su contenido, sea del tipo que sea, a la hora de procesar la página:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;strong&gt;&amp;lt;%-- &lt;/strong&gt;&lt;br /&gt;&lt;span style="COLOR:#009900;"&gt;  &amp;lt;script&amp;gt;&lt;br /&gt;    var count = &amp;lt;%= borrarRegistros() %&amp;gt;&lt;br /&gt;    alert(&amp;quot;Borrados: &amp;quot; + count + &amp;quot; registros&amp;quot;);&lt;br /&gt;  &amp;lt;/script&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;strong&gt;--%&amp;gt;&lt;/strong&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;En este caso ni sería ejecutada la función del servidor ni tampoco enviado a cliente el código HTML/Script incluido.&lt;br /&gt;&lt;br /&gt;Publicado en: &lt;a href="http://www.variablenotfound.com/"&gt;&lt;font color="#35537a"&gt;http://www.variablenotfound.com/&lt;/font&gt;&lt;/a&gt;. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=77390" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/c_2300_/default.aspx">c#</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/trucos/default.aspx">trucos</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/asp.net/default.aspx">asp.net</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/javascript/default.aspx">javascript</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vb.net/default.aspx">vb.net</category></item><item><title>Inicialización rápida de objetos en C# 3.0 y VB.Net 9.0</title><link>http://geeks.ms/blogs/jmaguilar/archive/2008/03/03/inicializaci-243-n-r-225-pida-de-objetos-en-c-3-0-y-vb-net-9-0.aspx</link><pubDate>Mon, 03 Mar 2008 19:57:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:76341</guid><dc:creator>José M. Aguilar</dc:creator><slash:comments>6</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/jmaguilar/rsscomments.aspx?PostID=76341</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2008/03/03/inicializaci-243-n-r-225-pida-de-objetos-en-c-3-0-y-vb-net-9-0.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://bp2.blogger.com/_O9D62hXq-ng/R8xWQWz3qKI/AAAAAAAAARo/9605cLwjjOo/s1600-h/programacion.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5173604910942890146" style="FLOAT:right;MARGIN:0px 0px 10px 10px;CURSOR:hand;" alt="Manos de afanoso desarrollador trabajando" src="http://bp2.blogger.com/_O9D62hXq-ng/R8xWQWz3qKI/AAAAAAAAARo/9605cLwjjOo/s320/programacion.jpg" border="0" /&gt;&lt;/a&gt;Como ya venimos &lt;a href="http://www.variablenotfound.com/search/label/vs2008"&gt;&lt;font color="#35537a"&gt;comentando hace tiempo&lt;/font&gt;&lt;/a&gt;, la nueva versión de ambos lenguajes viene repleta de novedades y mejoras pensadas para hacernos la vida más fácil y, por tanto, aumentar la productividad de los desarrolladoradores. Bueno, no sé si fue así o en realidad es que simplemente &lt;a title="La evolución de LINQ y su impacto en el diseño de C#" href="http://msdn.microsoft.com/msdnmag/issues/07/06/CSharp30/default.aspx?loc=es#S6"&gt;&lt;font color="#35537a"&gt;eran necesarias para Linq&lt;/font&gt;&lt;/a&gt; y por eso fueron incluidas ;-), pero el caso es que a partir de las versiones 3.0 y 9.0 de C# y VB.NET respectivamente, tenemos a nuestra disposición interesantísimas herramientas que deberíamos conocer para sacar el máximo provecho a nuestro tiempo.&lt;br /&gt;&lt;br /&gt;En esta ocasión vamos a centrarnos en los inicializadores de objetos, una nueva característica destinada, entre otras cosas, a ahorrarnos tiempo a la hora de establecer los valores iniciales de los objetos que creemos desde código.&lt;br /&gt;&lt;br /&gt;Y es que, hasta ahora, podíamos utilizar dos patrones básicos de inicialización de propiedades al instanciar una clase:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;que fuera la clase la que realizara esta tarea, ofreciendo al usuario de la misma constructores con distintas sobrecargas cuyos parámetros corresponden con las propiedades a inicializar.&lt;br /&gt;&lt;pre&gt;&lt;code&gt;// Constructor de la clase Persona:&lt;br /&gt;public Persona(string nombre, string apellidos, int edad, ...)&lt;br /&gt;{&lt;br /&gt;   this.Nombre = nombre;&lt;br /&gt;   this.Apellidos = apellidos;&lt;br /&gt;   this.Edad = edad;&lt;br /&gt;   ...&lt;br /&gt;}&lt;br /&gt;// Uso:&lt;br /&gt;Persona p = new Persona(&amp;quot;Juan&amp;quot;, &amp;quot;López&amp;quot;, 32, ...);&lt;/code&gt;&lt;/pre&gt;&amp;nbsp; 
&lt;li&gt;o bien dejar esta responsabilidad al usuario, permitiéndole el acceso directo a propiedades o campos del objeto creado.&lt;pre&gt;&lt;code&gt;// Uso:&lt;br /&gt;Persona p = new Persona();&lt;br /&gt;p.Nombre = &amp;quot;Juan&amp;quot;;&lt;br /&gt;p.Apellidos = &amp;quot;López&amp;quot;;&lt;br /&gt;p.Edad = 32;&lt;br /&gt;...&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Cualquiera de las dos formas anteriores, así como de opciones intermedias que combinen ambas ideas, tiene sus ventajas e inconvenientes, pero son igualmente tediosas. Si hablamos de clases con un gran número de propiedades, la cantidad de líneas de código necesarias para realizar una inicialización son realmente importantes.&lt;br /&gt;&lt;br /&gt;Los inicializadores de objetos permiten, en C# y VB.Net, realizar esta tarea de forma más simple, simplemente indicando en la llamada al constructor el valor de las propiedades o campos que deseemos establecer:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;// C#:&lt;br /&gt;Persona p = new Persona { Nombre=&amp;quot;Juan&amp;quot;, Apellidos=&amp;quot;López&amp;quot;, Edad=32 };&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&amp;#39; VB.NET:&lt;br /&gt;Dim p = New Persona With {.Nombre=&amp;quot;Luis&amp;quot;, .Apellidos=&amp;quot;López&amp;quot;, .Edad=32 }&lt;br /&gt;&lt;/p&gt;&lt;/code&gt;
&lt;p&gt;Los ejemplos anteriores son válidos para clases que admitan constructores sin parámetros, pero, ¿qué ocurre con los demás? Imaginando que el constructor de la clase &lt;code&gt;Persona&lt;/code&gt; recibe obligatoriamente dos parámetros, su nombre y apellidos, podríamos instanciar así:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;// C#:&lt;br /&gt;Persona p = new Persona (&amp;quot;Luis&amp;quot;, &amp;quot;López&amp;quot;) { Edad = 32 };&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;#39; VB.NET:&lt;br /&gt;Dim p = New Persona (&amp;quot;Luis&amp;quot;, &amp;quot;López&amp;quot;) With { .Edad = 32 }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Aunque es obvio, es importante tener en cuenta que las inicializaciones (la porción de código entre llaves &amp;quot;{&amp;quot; y &amp;quot;}&amp;quot;) se ejecutan después del constructor:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;&lt;br /&gt;// C#:&lt;br /&gt;Persona p = new Persona (&amp;quot;Juan&amp;quot;, &amp;quot;Pérez&amp;quot;) { Nombre=&amp;quot;Luis&amp;quot; };&lt;br /&gt;Console.WriteLine(p.Nombre); // Escribe &amp;quot;Luis&amp;quot;&lt;br /&gt;&lt;br /&gt;&amp;#39; VB.NET:&lt;br /&gt;Dim p = New Persona (&amp;quot;Juan&amp;quot;, &amp;quot;Pérez&amp;quot;) With { .Nombre=&amp;quot;Luis&amp;quot; }&lt;br /&gt;Console.WriteLine(p.Nombre); &amp;#39; Escribe &amp;quot;Luis&amp;quot;&lt;br /&gt;&lt;/p&gt;&lt;/code&gt;
&lt;p&gt;Y un último apunte: ¿cómo inicializaríamos propiedades de objetos que a su vez sean objetos que también queremos inicializar? Suponiendo que en nuestra clase &lt;code&gt;Persona&lt;/code&gt; hemos incluido una propiedad llamada &lt;code&gt;Domicilio&lt;/code&gt; que de tipo &lt;code&gt;Localizacion&lt;/code&gt;, podríamos inicializar el bloque completo así:&lt;br /&gt;&lt;code&gt;&lt;br /&gt;// C#:&lt;br /&gt;// Se han cortado las líneas para facilitar la lectura&lt;br /&gt;Persona p = new Persona() &lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Nombre = &amp;quot;Juan&amp;quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Apellidos = &amp;quot;López&amp;quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Edad = 55,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Domicilio = new Localizacion &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Direccion = &amp;quot;Callejas, 34&amp;quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Localidad = &amp;quot;Sevilla&amp;quot;,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Provincia = &amp;quot;Sevilla&amp;quot;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;};&lt;br /&gt;&lt;br /&gt;&amp;#39; VB.NET:&lt;br /&gt;&amp;#39; Se han cortado las líneas para facilitar la lectura&lt;br /&gt;Dim p = New Persona() With { _&lt;br /&gt;&amp;nbsp; .Nombre = &amp;quot;Juan&amp;quot;, _&lt;br /&gt;&amp;nbsp; .Apellidos = &amp;quot;López&amp;quot;, _&lt;br /&gt;&amp;nbsp; .Edad = 55, _&lt;br /&gt;&amp;nbsp; .Domicilio = New Localizacion With { _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Direccion = &amp;quot;Callejas, 23&amp;quot;, _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Localidad = &amp;quot;Sevilla&amp;quot;, _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; .Provincia = &amp;quot;Sevilla&amp;quot; _&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } _&lt;br /&gt;&amp;nbsp; }&lt;br /&gt;&lt;/code&gt;&amp;nbsp;&lt;br /&gt;En fin, que de nuevo tenemos ante nosotros una característica de estos lenguajes que resulta interesante por sí misma, aunque toda su potencia y utilidad podremos percibirla cuando profundicemos en otras novedades, como los tipos anónimos y Linq... aunque eso será otra historia.&lt;br /&gt;&lt;br /&gt;Publicado en: &lt;a href="http://www.variablenotfound.com/"&gt;&lt;font color="#35537a"&gt;http://www.variablenotfound.com/&lt;/font&gt;&lt;/a&gt;. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=76341" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/desarrollo/default.aspx">desarrollo</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/programaci_26002300_243_3B00_n/default.aspx">programaci&amp;#243;n</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/c_2300_/default.aspx">c#</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/.net/default.aspx">.net</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vs2008/default.aspx">vs2008</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vb.net/default.aspx">vb.net</category></item><item><title>Saber si una cadena está vacía usando métodos de extensión (C#/VB.Net)</title><link>http://geeks.ms/blogs/jmaguilar/archive/2008/02/24/saber-si-una-cadena-est-225-vac-237-a-usando-m-233-todos-de-extensi-243-n-c-vb-net.aspx</link><pubDate>Sun, 24 Feb 2008 20:05:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:74068</guid><dc:creator>José M. Aguilar</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/jmaguilar/rsscomments.aspx?PostID=74068</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2008/02/24/saber-si-una-cadena-est-225-vac-237-a-usando-m-233-todos-de-extensi-243-n-c-vb-net.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://bp2.blogger.com/_O9D62hXq-ng/R8HNWwvIyeI/AAAAAAAAARg/bri51ZijKvk/s1600-h/cscode.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5170639638121466338" style="FLOAT:right;MARGIN:0px 0px 10px 10px;CURSOR:hand;" alt="" src="http://bp2.blogger.com/_O9D62hXq-ng/R8HNWwvIyeI/AAAAAAAAARg/bri51ZijKvk/s320/cscode.png" border="0" /&gt;&lt;/a&gt;Hace unos meses comentaba las distintas opciones para saber &lt;a href="http://www.variablenotfound.com/2008/10/saber-si-una-cadena-est-vaca-en-c.html"&gt;&lt;font color="#35537a"&gt;si una cadena está vacía en C#&lt;/font&gt;&lt;/a&gt;, y la conclusión era la recomendación del uso del método estático &lt;code&gt;string.IsNullOrEmpty&lt;/code&gt;, sobre todo si podemos asegurar que no aparecerá el &lt;a href="http://elbruno.com/blogs/vtortola/archive/2007/07/30/el-bug-de-string-isnullorempty-en-net-2-0.aspx"&gt;&lt;font color="#35537a"&gt;famoso bug&lt;/font&gt;&lt;/a&gt; del mismo (que al final &lt;a title="[ING] El peligro de String.IsNullOrEmpty()" href="http://www.omegacoder.com/?p=105"&gt;&lt;font color="#35537a"&gt;no es para tanto&lt;/font&gt;&lt;/a&gt;, todo sea dicho).&lt;br /&gt;&lt;br /&gt;Los &lt;a href="http://www.variablenotfound.com/2008/02/mtodos-de-extensin-en-c.html"&gt;&lt;font color="#35537a"&gt;métodos de extensión&lt;/font&gt;&lt;/a&gt; nos brindan la posibilidad de hacer lo mismo pero de una forma más elegante e intuitiva, impensable hasta la llegada de C# 3.0: extendiendo la clase &lt;code&gt;string&lt;/code&gt; con un método que compruebe su contenido.&lt;br /&gt;&lt;br /&gt;La forma de conseguirlo es bien sencilla. Declaramos en una clase estática el método de extensión sobre el tipo &lt;code&gt;string&lt;/code&gt;:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;public static class MyExtensions&lt;br /&gt;{&lt;br /&gt;    public static bool IsNullOrEmpty(this string s)&lt;br /&gt;    {&lt;br /&gt;        return s == null || s.Length == 0;&lt;br /&gt;    }&lt;br /&gt;}&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Y listo, ya tenemos el nuevo método listo para ser utilizado:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;string name = getCurrentUserName();&lt;br /&gt;if (!name.IsNullOrEmpty())&lt;br /&gt;...&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;De todas formas, hay un par de reflexiones que considero interesante comentar.&lt;br /&gt;&lt;br /&gt;En primer lugar, fijaos en el ejemplo anterior que aunque la variable &lt;code&gt;name&lt;/code&gt; contenga un nulo, se ejecutará la llamada a &lt;code&gt;IsNullOrEmpty()&lt;/code&gt; sin provocar error, algo imposible si se tratara de un método de instancia. Obviamente, se debe a que en realidad se está enmascarando una llamada a un método estático al que le llegará como parámetro un &lt;code&gt;null&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Como consecuencia de lo anterior, y dado que no se puede distinguir a simple vista en una llamada a un método si éste es de instancia o de extensión, es posible que un desarrollador considerara esta invocación incorrecta. Esto forma parte de los &lt;a href="http://www.variablenotfound.com/2008/02/mtodos-de-extensin-en-c.html"&gt;&lt;font color="#35537a"&gt;inconvenientes de los métodos de extensión&lt;/font&gt;&lt;/a&gt; que ya cité en un post anterior.&lt;br /&gt;&lt;br /&gt;En segundo lugar, visto lo visto cabría preguntarse, ¿por qué podemos extender una clase añadiéndole nuevos métodos pero no es posible incluir otro tipo de elementos, como eventos o propiedades? En el caso anterior podría quedar más fino que &lt;code&gt;IsNullOrEmpty&lt;/code&gt; fuera una propiedad de &lt;code&gt;string&lt;/code&gt;, ¿no? &lt;br /&gt;&lt;br /&gt;Sin embargo, esto no es posible de momento. Según comentó &lt;a title="[ING] Extension Methods" href="http://weblogs.asp.net/scottgu/archive/2007/03/13/new-orcas-language-feature-extension-methods.aspx"&gt;&lt;font color="#35537a"&gt;ScottGu&lt;/font&gt;&lt;/a&gt; hace tiempo, se estaba considerando añadir la posibilidad de extender las clases también con nuevas propiedades. Supongo que el hecho de no haberla incluido en esta versión se deberá a que no era necesario para LINQ, la estrella de esta entrega... ¡y para dejar algo por hacer para C# 4.0, claro! ;-)&lt;br /&gt;&lt;br /&gt;En cualquier caso, se trata principalmente de una cuestión de estética del código. Todo lo que conseguimos con las propiedades se puede realizar a base de métodos; de hecho, las propiedades no son sino interfaces más agradables a métodos &lt;em&gt;getters&lt;/em&gt; y &lt;em&gt;setters&lt;/em&gt;, al más puro estilo Java, subyacentes.&lt;br /&gt;&lt;br /&gt;Por último, todo lo dicho es válido para VB.NET 9, salvo las obvias diferencias. El código equivalente al anterior sería:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;Imports System.Runtime.CompilerServices&lt;br /&gt;Module MyExtensions&lt;br /&gt;    &amp;lt;Extension()&amp;gt; _&lt;br /&gt;    Public Function IsNullOrEmtpy(ByVal s As String) As String&lt;br /&gt;        Return (s = Nothing) OrElse (s.Length = 0)&lt;br /&gt;    End Function&lt;br /&gt;End Module&lt;br /&gt;[...]&lt;br /&gt;&lt;br /&gt;&amp;#39; Forma de invocar el método:&lt;br /&gt;If s.IsNullOrEmtpy() Then&lt;br /&gt;[...]&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Publicado en: &lt;a href="http://www.variablenotfound.com/"&gt;&lt;font color="#35537a"&gt;http://www.variablenotfound.com/&lt;/font&gt;&lt;/a&gt;. &lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=74068" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/desarrollo/default.aspx">desarrollo</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/programaci_26002300_243_3B00_n/default.aspx">programaci&amp;#243;n</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/c_2300_/default.aspx">c#</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vs2008/default.aspx">vs2008</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vb.net/default.aspx">vb.net</category></item><item><title>Variables locales implicítamente tipadas en VB.NET 9</title><link>http://geeks.ms/blogs/jmaguilar/archive/2008/01/09/variables-locales-implic-237-tamente-tipadas-en-vb-net-9.aspx</link><pubDate>Wed, 09 Jan 2008 18:01:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:62473</guid><dc:creator>José M. Aguilar</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/jmaguilar/rsscomments.aspx?PostID=62473</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2008/01/09/variables-locales-implic-237-tamente-tipadas-en-vb-net-9.aspx#comments</comments><description>&lt;p&gt;
                                            &lt;a href="http://bp0.blogger.com/_O9D62hXq-ng/R1wqKi1EX9I/AAAAAAAAAOM/aoA1asmsP6c/s1600-h/source_code.jpg"&gt;&lt;img src="http://bp0.blogger.com/_O9D62hXq-ng/R1wqKi1EX9I/AAAAAAAAAOM/aoA1asmsP6c/s320/source_code.jpg" style="margin:2px 10px 10px 2px;float:left;cursor:pointer;" alt="" id="BLOGGER_PHOTO_ID_5142031235186712530" border="0" /&gt;&lt;/a&gt;Visual
Basic .NET 9.0, disponible con Visual Studio 2008, incluye, al igual
que C# 3.0, multitud de novedades y mejoras que sin duda nos harán la
vida más fácil. &lt;br /&gt;&lt;br /&gt;Una de ellas es la posibilidad de declarar
variables sin necesidad de indicar de forma explícita su tipo, cediendo
al compilador la tarea de determinar cuál es en función del tipo de
dato obtenido al evaluar su expresión de inicialización. El tipado
implícito o inferencia de tipos también existe en C# y ya &lt;a href="http://www.variablenotfound.com/2007/12/variables-locales-implictamente-tipadas.html"&gt;escribí sobre ello hace unos días&lt;/a&gt;, pero me parecía interesante también publicar la visión para el programador Visual Basic y las particularidades que presenta.&lt;br /&gt;&lt;br /&gt;Gracias a esta nueva característica, en lugar de escribir: &lt;/p&gt;&lt;pre&gt;&lt;code&gt;  Dim x As XmlDateTimeSerializationMode = XmlDateTimeSerializationMode.Local&lt;br /&gt;  Dim i As Integer = 1&lt;br /&gt;  Dim d As Double = 1.8&lt;/code&gt;&lt;/pre&gt;podremos utilizar:&lt;pre&gt;&lt;code&gt;  Dim x = XmlDateTimeSerializationMode.Local&lt;br /&gt;  Dim i = 1&lt;br /&gt;  Dim d = 1.8&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;El
resultado en ambos casos será idéntico, ganando en comodidad y
eficiencia a la hora de la codificación y sin sacrificar los beneficios
propios del tipado fuerte. &lt;br /&gt;&lt;br /&gt;Hay un detalle importante que los
veteranos habrán observado: Visual Basic ya permitía (y de hecho
permite) la declaración de variables sin especificar el tipo, de la
forma &lt;code&gt;Dim i = 1&lt;/code&gt; (con &lt;code&gt;Option Strict Off&lt;/code&gt;), por
lo que podría parecer que el tipado implícito no sería necesario. Sin
embargo, en este caso los compiladores asumían que la variable era de
tipo &lt;em&gt;Object&lt;/em&gt;, por lo que nos veíamos obligados a realizar
castings o conversiones en tiempo de ejecución, penalizando el
rendimiento y aumentando el riesgo de aparición de errores imposibles
de detectar en compilación. Tampoco tiene nada que ver con tipados
dinámicos (como los presentes en &lt;em&gt;javascript&lt;/em&gt;), o con el famoso tipo &lt;code&gt;Variant&lt;/code&gt;
que estaba presente en Visual Basic 6; el tipo asignado a la variable
es fijo e inamovible, como si lo hubiésemos declarado explícitamente.&lt;br /&gt;&lt;br /&gt;En Visual Basic 9, siempre que no se desactive esta característica incluyendo la directiva &lt;code&gt;Option Infer Off&lt;/code&gt;
en el código, el tipo de la variable será fijado justo en el momento de
su declaración, deduciéndolo a partir del tipo devuelto por la
expresión de inicialización. Por este motivo, la declaración y la
inicialización deberán hacerse en el mismo momento:&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  Dim i = 1 &amp;#39; La variable &amp;quot;i&amp;quot; es Integer desde este momento&lt;br /&gt;&lt;br /&gt;  Dim j     &amp;#39; La variable &amp;quot;j&amp;quot; es Object, como siempre, &lt;br /&gt;  j = 1     &amp;#39; ... si Option Scrict está en Off. &lt;br /&gt;            &amp;#39; En caso contrario aparecerá un error de compilación.&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;El tipado implícito puede ser asimismo utilizado en las variables de control de bucles &lt;em&gt;For&lt;/em&gt; o &lt;em&gt;For Each&lt;/em&gt;, haciendo su escritura mucho más cómoda:&lt;br /&gt;&lt;pre&gt;&lt;code&gt; &lt;br /&gt;  Dim suma = 0&lt;br /&gt;  For i = 1 To 10       &amp;#39; i se está declarando ahí mismo como Integer,&lt;br /&gt;    suma += i           &amp;#39; no existía con anterioridad&lt;br /&gt;  Next&lt;br /&gt;&lt;br /&gt;  Dim str = &amp;quot;abcdefg&amp;quot;&lt;br /&gt;  For Each ch In str    &amp;#39; ch se declara automáticamente como char,&lt;br /&gt;      Console.Write(ch) &amp;#39; que es el tipo de los elementos de &amp;quot;str&amp;quot;&lt;br /&gt;  Next&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;Y
también puede resultar bastante útil a la hora de obtener objetos de
tipos anónimos, es decir, aquellos cuya clase se define en el mismo
momento de su instanciación, como en el siguiente ejemplo:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  Dim point = New With {.X = 1, .Y = 5}&lt;br /&gt;  point.X += 1&lt;br /&gt;  point.Y += 1&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Por
último, es interesante comentar que, a diferencia de C#, Visual Basic
permite declarar en la misma línea distintas variables de tipo
implícito, por lo que es posible escribir &lt;code&gt;Dim k=1, j=4.8, str=&amp;quot;Hola&amp;quot;&lt;/code&gt;
sin temor a un error en compilación, asignándose a cada una de ellas el
tipo apropiado en función de su inicialización (en el ejemplo, &lt;em&gt;Integer&lt;/em&gt;, &lt;em&gt;Double &lt;/em&gt;y &lt;em&gt;String &lt;/em&gt;respectivamente).&lt;br /&gt;&lt;br /&gt;Coinciden,
sin embargo, en que en ambos lenguajes esta forma de declaración de
variables se aplica exclusivamente a las locales, es decir, aquellas
cuyo ámbito es un método, función o bloque de código. No pueden ser
propiedades ni variables de instancia; en el siguiente ejemplo, &lt;em&gt;x&lt;/em&gt; será declarada de forma implícita como &lt;em&gt;Object&lt;/em&gt;, mientras que el tipo de la variable &lt;em&gt;y&lt;/em&gt; será inferido como &lt;em&gt;Integer&lt;/em&gt;:&lt;br /&gt;&lt;pre&gt;&lt;code&gt;  Public Class Class1&lt;br /&gt;    Dim x = 2        &amp;#39; Es una variable de instancia&lt;br /&gt;    Public Sub New()&lt;br /&gt;        Dim y = 2    &amp;#39; Es una variable local&lt;br /&gt;    End Sub&lt;br /&gt;  End Class&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;En
resumen, se trata de una característica muy útil que, además de
permitirnos programar más rápidamente al ahorrarnos teclear los tipos
de las variables locales, actúa como soporte de nuevas características
del lenguaje y la plataforma .NET, como el interesantísimo &lt;a href="http://www.variablenotfound.com/2006/05/linq-integracin-de-consultas-en-el.html"&gt;Linq&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Es
conveniente, sin embargo, utilizar esta característica con cordura y
siendo siempre conscientes de que su uso puede dar lugar a un código
menos legible y generar errores difíciles de depurar. De hecho,
Microsoft recomienda usarlas &amp;quot;sólo cuando sea conveniente&amp;quot;.&lt;br /&gt;&lt;br /&gt;Publicado en: &lt;a href="http://www.variablenotfound.com/"&gt;Variable Not Found&lt;/a&gt;.&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=62473" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/programaci_26002300_243_3B00_n/default.aspx">programaci&amp;#243;n</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vs2008/default.aspx">vs2008</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vb.net/default.aspx">vb.net</category></item></channel></rss>