<?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 : vs2008</title><link>http://geeks.ms/blogs/jmaguilar/archive/tags/vs2008/default.aspx</link><description>Etiquetas: vs2008</description><dc:language /><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><item><title>Error al conectarse al administrador de deshacer del archivo de código fuente</title><link>http://geeks.ms/blogs/jmaguilar/archive/2010/02/22/error-al-conectarse-al-administrador-de-deshacer-del-archivo-de-c-243-digo-fuente.aspx</link><pubDate>Mon, 22 Feb 2010 09:12:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:167903</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=167903</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2010/02/22/error-al-conectarse-al-administrador-de-deshacer-del-archivo-de-c-243-digo-fuente.aspx#comments</comments><description>&amp;ldquo;Error al conectarse al administrador de deshacer del archivo de c&amp;oacute;digo fuente c:\blahblah\archivo.designer.cs&amp;rdquo; es un mensaje con el que Visual Studio (tanto la versi&amp;oacute;n 2005 como 2008) me ha abofeteado en numerosas ocasiones cuando estoy desarrollando sitios web ASP.NET. Y la verdad, es uno de esos casos en los que no sabes qu&amp;eacute; hacer: recompilas, limpias la soluci&amp;oacute;n, abres y cierras el IDE&amp;hellip; pero nada, cuando le da por ah&amp;iacute;, no hay forma de hacerlo...(&lt;a href="http://geeks.ms/blogs/jmaguilar/archive/2010/02/22/error-al-conectarse-al-administrador-de-deshacer-del-archivo-de-c-243-digo-fuente.aspx"&gt;read more&lt;/a&gt;)&lt;img src="http://geeks.ms/aggbug.aspx?PostID=167903" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/trucos/default.aspx">trucos</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vs2008/default.aspx">vs2008</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/herramientas/default.aspx">herramientas</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vs2005/default.aspx">vs2005</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/error/default.aspx">error</category></item><item><title>Compilar las vistas en ASP.NET MVC</title><link>http://geeks.ms/blogs/jmaguilar/archive/2009/06/03/compilar-las-vistas-en-asp-net-mvc.aspx</link><pubDate>Wed, 03 Jun 2009 21:04:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:149779</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=149779</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2009/06/03/compilar-las-vistas-en-asp-net-mvc.aspx#comments</comments><description>&lt;div class="post-header-line-1"&gt;&lt;/div&gt;
&lt;div class="post-body entry-content"&gt;
&lt;p&gt;&amp;nbsp;&lt;img height="83" width="232" src="http://lh3.ggpht.com/_O9D62hXq-ng/SgR1XiQ8TPI/AAAAAAAABC4/plYPyED3xK4/image%5B8%5D.png?imgmax=800" align="right" alt="Yellow Screen of Death" border="0" title="Yellow Screen of Death" style="margin:0px 0px 5px 5px;display:inline;border-width:0px;" /&gt;El c&amp;oacute;digo introducido en las vistas ASP.NET MVC pueden ser fuente de problemas en tiempo de ejecuci&amp;oacute;n debido a que, por defecto, no se compilan con el proyecto, sino cuando el sistema necesita mostrarlas por primera vez. Es decir, es perfectamente posible que errores de codificaci&amp;oacute;n en un archivo .ASPX no sean detectados hasta el momento de su ejecuci&amp;oacute;n, provocando un &lt;a hreflang="en" href="http://en.wikipedia.org/wiki/Screens_of_death#ASP.NET" title="Yellow Screen of Death"&gt;YSOD&lt;/a&gt;&lt;a href="http://en.wikipedia.org/wiki/Screens_of_death#ASP.NET" title="Yellow Screen of Death"&gt;&lt;/a&gt; de los de toda la vida.&lt;/p&gt;
&lt;p&gt;Un ejemplo. Imaginemos una vista tipada (en un archivo .ASPX) en la que hemos incluido el siguiente c&amp;oacute;digo,&lt;em&gt; perfectamente v&amp;aacute;lido&amp;hellip;&lt;/em&gt;&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:5d049fea-50da-48b3-a037-217cd68838f3" style="margin:0px;display:inline;float:none;padding:0px;"&gt;
&lt;pre style="background-color:#ffffff;word-wrap:break-word;white-space:pre-wrap;overflow:auto;"&gt;&lt;span style="background-color:#ffff00;color:#000000;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="background-color:#f5f5f5;color:#000000;"&gt;@ Page Language&lt;/span&gt;&lt;span style="background-color:#f5f5f5;color:#000000;"&gt;=&lt;/span&gt;&lt;span style="background-color:#f5f5f5;color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="background-color:#f5f5f5;color:#800000;"&gt;C#&lt;/span&gt;&lt;span style="background-color:#f5f5f5;color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="background-color:#f5f5f5;color:#000000;"&gt; MasterPageFile&lt;/span&gt;&lt;span style="background-color:#f5f5f5;color:#000000;"&gt;=&lt;/span&gt;&lt;span style="background-color:#f5f5f5;color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="background-color:#f5f5f5;color:#800000;"&gt;~/Views/Shared/Site.Master&lt;/span&gt;&lt;span style="background-color:#f5f5f5;color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="background-color:#f5f5f5;color:#000000;"&gt; &lt;br /&gt;         Inherits&lt;/span&gt;&lt;span style="background-color:#f5f5f5;color:#000000;"&gt;=&lt;/span&gt;&lt;span style="background-color:#f5f5f5;color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="background-color:#f5f5f5;color:#800000;"&gt;System.Web.Mvc.ViewPage&amp;lt;Persona&amp;gt;&lt;/span&gt;&lt;span style="background-color:#f5f5f5;color:#800000;"&gt;&amp;quot;&lt;/span&gt;&lt;span style="background-color:#f5f5f5;color:#000000;"&gt; &lt;/span&gt;&lt;span style="background-color:#ffff00;color:#000000;"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;[...]&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;h2&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;Datos personales&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;h2&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;Nombre: &lt;/span&gt;&lt;span style="background-color:#ffff00;color:#000000;"&gt;&amp;lt;%&lt;/span&gt;&lt;span style="background-color:#f5f5f5;color:#000000;"&gt;=&lt;/span&gt;&lt;span style="background-color:#f5f5f5;color:#000000;"&gt; this.Model.Nombre &lt;/span&gt;&lt;span style="background-color:#ffff00;color:#000000;"&gt;%&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;&lt;br /&gt;[...]&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;em&gt;&amp;hellip; perfectamente v&amp;aacute;lido&lt;/em&gt; mientras la clase &lt;code&gt;Persona&lt;/code&gt; tenga una propiedad que se llame &lt;code&gt;Nombre&lt;/code&gt;. Si eliminamos esta propiedad o simplemente cambiamos su nombre, la refactorizaci&amp;oacute;n autom&amp;aacute;tica del IDE no se realizar&amp;aacute; sobre el c&amp;oacute;digo de la vista, y se generar&amp;aacute; un error en ejecuci&amp;oacute;n en cuanto intentemos acceder a ella, es decir, &lt;strong&gt;estaremos llevando a tiempo de ejecuci&amp;oacute;n problemas propios del tiempo de compilaci&amp;oacute;n.&lt;/strong&gt;
&lt;p&gt;Afortunadamente, ASP.NET MVC framework incluye un mecanismo que nos permite forzar la compilaci&amp;oacute;n de las vistas y, as&amp;iacute;, detectar estos problemas de forma temprana, antes de poner el sitio en producci&amp;oacute;n. &lt;/p&gt;
&lt;p&gt;Para activarlo, lo primero que hay que hacer es abrir el archivo del proyecto (.csproj o .vbproj) con cualquier editor de textos, como el block de notas, localizar en las primeras l&amp;iacute;neas el comienzo de la secci&amp;oacute;n &lt;code&gt;PropertyGroup, &lt;/code&gt;e insertar justo despu&amp;eacute;s la declaraci&amp;oacute;n que habilita la compilaci&amp;oacute;n de las vistas:&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:cf2daa20-08af-40d2-b614-3a9f0df5cbfd" style="margin:0px;display:inline;float:none;padding:0px;"&gt;
&lt;pre style="background-color:#ffffff;word-wrap:break-word;white-space:pre-wrap;overflow:auto;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;PropertyGroup&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;MvcBuildViews&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;true&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;MvcBuildViews&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;   [...]&lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;PropertyGroup&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;   &lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Ojo a un detalle: es posible que en alg&amp;uacute;n punto del archivo del proyecto exista una declaraci&amp;oacute;n que anule la anterior as&amp;iacute;: &lt;code&gt;&amp;lt;MvcBuildViews&amp;gt;false&amp;lt;/MvcBuildViews&amp;gt;&lt;/code&gt;. Deb&amp;eacute;is eliminar esa l&amp;iacute;nea, pues de lo contrario no se activar&amp;aacute; esta caracter&amp;iacute;stica.&lt;/p&gt;
&lt;p&gt;Acto seguido, debemos asegurarnos de que exista el siguiente c&amp;oacute;digo cerca del final del archivo; en mi caso ya exist&amp;iacute;a, pero si no es as&amp;iacute; debemos insertarlo, por ejemplo, justo antes del cierre del documento (en la l&amp;iacute;nea anterior a &lt;code&gt;&amp;lt;/Projects&amp;gt;&lt;/code&gt;).&lt;/p&gt;
&lt;div class="wlWriterEditableSmartContent" id="scid:57F11A72-B0E5-49c7-9094-E3A15BD5B5E6:3d0a91dd-bb7d-4284-8c15-99a8a26c3e8a" style="margin:0px;display:inline;float:none;padding:0px;"&gt;
&lt;pre style="background-color:#ffffff;word-wrap:break-word;white-space:pre-wrap;overflow:auto;"&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;Target &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;Name&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;AfterBuild&amp;quot;&lt;/span&gt;&lt;span style="color:#ff0000;"&gt; Condition&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;&amp;#39;$(MvcBuildViews)&amp;#39;==&amp;#39;true&amp;#39;&amp;quot;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt;&lt;br /&gt;   &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;&lt;/span&gt;&lt;span style="color:#800000;"&gt;AspNetCompiler &lt;/span&gt;&lt;span style="color:#ff0000;"&gt;VirtualPath&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;temp&amp;quot;&lt;/span&gt;&lt;span style="color:#ff0000;"&gt; &lt;br /&gt;                   PhysicalPath&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;=&amp;quot;$(ProjectDir)\..\$(ProjectName)&amp;quot;&lt;/span&gt;&lt;span style="color:#ff0000;"&gt; &lt;/span&gt;&lt;span style="color:#0000ff;"&gt;/&amp;gt;&lt;/span&gt;&lt;span style="color:#000000;"&gt; &lt;br /&gt;&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;lt;/&lt;/span&gt;&lt;span style="color:#800000;"&gt;Target&lt;/span&gt;&lt;span style="color:#0000ff;"&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;p&gt;Una vez guardado el archivo, recargamos la soluci&amp;oacute;n en Visual Studio, y listo. Eso s&amp;iacute;, a partir de este momento tendremos que esperar un poco m&amp;aacute;s durante la generaci&amp;oacute;n del proyecto, pero la seguridad que aporta bien vale la pena.&lt;/p&gt;
&lt;p&gt;Fuente: &lt;a hreflang="en" href="http://stackoverflow.com/questions/383192/compile-views-in-asp-net-mvc" title="Compile Views in ASP.NET MVC - Stack Overflow"&gt;Compile Views in ASP.NET MVC - Stack Overflow&lt;/a&gt;&lt;a href="http://stackoverflow.com/questions/383192/compile-views-in-asp-net-mvc" title="Compile Views in ASP.NET MVC - Stack Overflow"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Publicado en: &lt;a href="http://www.variablenotfound.com/" title="Variable Not Found"&gt;&lt;span style="color:#35537a;"&gt;Variable not found&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=149779" 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/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/vs2008/default.aspx">vs2008</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/aspnetmvc/default.aspx">aspnetmvc</category></item><item><title>Plantillas de proyectos ASP.NET MVC 1.0 para NUnit</title><link>http://geeks.ms/blogs/jmaguilar/archive/2009/05/18/plantillas-de-proyectos-asp-net-mvc-1-0-para-nunit.aspx</link><pubDate>Mon, 18 May 2009 21:27:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:148670</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=148670</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2009/05/18/plantillas-de-proyectos-asp-net-mvc-1-0-para-nunit.aspx#comments</comments><description>&lt;p&gt;Joe Cartano, perteneciente al Visual Web Development Team de Microsoft, ha publicado en el blog oficial (&lt;a href="http://blogs.msdn.com/webdevtools/default.aspx" title="Visual Web Developer Team Blog"&gt;&lt;span style="color:#35537a;"&gt;Visual Web Developer Team &lt;/span&gt;&lt;/a&gt;&lt;a hreflang="en" href="http://blogs.msdn.com/webdevtools/default.aspx" title="Visual Web Developer Team Blog"&gt;Blog&lt;/a&gt;) un post anunciando que ha actualizado la plantilla que permite crear directamente proyectos ASP.NET MVC con tests unitarios &lt;a hreflang="en" href="http://www.nunit.org" title="NUnit"&gt;NUnit&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As&amp;iacute;, una vez instalado, al crear un proyecto de tipo ASP.NET MVC nos aparecer&amp;aacute; un cuadro de di&amp;aacute;logo como el siguiente, en el que se nos brindar&amp;aacute; la oportunidad de crear en la soluci&amp;oacute;n un proyecto de pruebas unitarias utilizando NUnit:&lt;/p&gt;
&lt;p&gt;&lt;img height="225" width="325" src="http://lh5.ggpht.com/_O9D62hXq-ng/SgRnjqs-QUI/AAAAAAAABCw/h0AdXjB8ppM/image%5B14%5D.png?imgmax=800" alt="Crear proyecto de pruebas unitarias" border="0" title="Crear proyecto de pruebas unitarias" style="margin:0px auto 5px;display:block;float:none;border:0px;" /&gt;&lt;/p&gt;
&lt;p&gt;Para los poseedores de algunas de las versiones profesionales de Visual Studio 2008, esta ventana no es nueva, puesto que por defecto ya se incluyen los proyectos de tests propios de Microsoft, pero s&amp;iacute; lo es para la versi&amp;oacute;n express del IDE, que no incluye el framework de pruebas y en el que hab&amp;iacute;a que crear el proyecto a mano.&lt;/p&gt;
&lt;p&gt;El proyecto, que se crea autom&amp;aacute;ticamente, realiza 27 tests sobre la plantilla original de proyectos ASP.NET MVC, y pueden servir como base para seguir creando nuestro propio conjunto de pruebas:&lt;/p&gt;
&lt;p&gt;&lt;img height="238" width="367" src="http://lh3.ggpht.com/_O9D62hXq-ng/SgRnk2XzKHI/AAAAAAAABC0/uIA5GhjfcXA/image%5B25%5D.png?imgmax=800" alt="&amp;iexcl;La plantilla ASP.NET MVC valida!" border="0" title="&amp;iexcl;La plantilla ASP.NET MVC valida!" style="margin:0px auto 5px;display:block;float:none;border:0px;" /&gt; &lt;/p&gt;
&lt;p&gt;La plantilla se instala descargando el archivo .zip cuyo enlace encontrar&amp;eacute;is en &lt;a hreflang="en" href="http://blogs.msdn.com/webdevtools/archive/2009/04/28/updated-nunit-templates-for-asp-net-mvc-1-0-rtm.aspx" title="Updated NUnit Templates for ASP.Net MVC 1.0 RTM"&gt;el post original&lt;/a&gt; y ejecutando, si es necesario con un usuario con privilegios de administrador, el script &lt;code&gt;installNUnit.cmd&lt;/code&gt; disponible en el ra&amp;iacute;z del directorio donde lo hay&amp;aacute;is descomprimido.&lt;/p&gt;
&lt;p&gt;Para que todo vaya bien, deb&amp;eacute;is contar con &lt;a hreflang="en" href="http://www.nunit.org" title="NUnit"&gt;NUnit&lt;/a&gt; previamente instalado en vuestro equipo. Pero ojo, las plantillas est&amp;aacute;n preparadas para la versi&amp;oacute;n 2.4.8.0 y la versi&amp;oacute;n actual es la 2.5.0.9122, por lo que puede que no os funcionen bien si est&amp;aacute;is a la &amp;uacute;ltima.&lt;/p&gt;
&lt;p&gt;En este caso, es necesario tocar a mano los archivos de plantillas. Pod&amp;eacute;is seguir estos pasos:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Descargad el archivo de plantillas &lt;a hreflang="en" href="http://blogs.msdn.com/webdevtools/archive/2009/04/28/updated-nunit-templates-for-asp-net-mvc-1-0-rtm.aspx" title="Plantillas para NUnit y ASP.NET MVC"&gt;desde el blog del Visual Web Developer Team&lt;/a&gt;&lt;a href="http://blogs.msdn.com/webdevtools/archive/2009/04/28/updated-nunit-templates-for-asp-net-mvc-1-0-rtm.aspx" title="Plantillas para NUnit y ASP.NET MVC"&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Descomprimidlo sobre cualquier carpeta.&lt;/li&gt;
&lt;li&gt;En los subdirectorios CSharp y Visual Basic encontrar&amp;eacute;is un archivo llamado &lt;code&gt;MvcApplication.NUnit.Tests.zip&lt;/code&gt;. Son las plantillas para cada uno de esos lenguajes.&lt;/li&gt;
&lt;li&gt;El interior de dicho zip est&amp;aacute; el archivo de proyecto (&lt;code&gt;MvcApplication.NUnit.Test.vbproj&lt;/code&gt; en el caso de Visual Basic, &lt;code&gt;MvcApplication.NUnit.Test.csproj&lt;/code&gt; en C#). Descomprimid s&amp;oacute;lo estos archivos y buscar en ambos la cadena &amp;ldquo;2.4.8.0&amp;rdquo; y sustituirla por la versi&amp;oacute;n de NUnit que teng&amp;aacute;is instalada (en mi caso, &amp;ldquo;2.5.0.9122&amp;rdquo;). Al acabar, actualizad de nuevo el .zip con el archivo que acab&amp;aacute;is de editar.&lt;/li&gt;
&lt;li&gt;Ejecutad el script de instalaci&amp;oacute;n &lt;code&gt;installNUnit.cmd&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Crossposteando desde: &lt;a href="http://www.variablenotfound.com/2009/05/plantillas-de-proyectos-aspnet-mvc-10.html" title="Plantillas de proyectos ASP.NET MVC 1.0 para NUnit"&gt;&lt;span style="color:#35537a;"&gt;Variable not found&lt;/span&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=148670" 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/asp.net/default.aspx">asp.net</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/buenas+pr_26002300_225_3B00_cticas/default.aspx">buenas pr&amp;#225;cticas</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/aspnetmvc/default.aspx">aspnetmvc</category></item><item><title>C#: Desmitificando las expresiones lambda (y III)</title><link>http://geeks.ms/blogs/jmaguilar/archive/2009/04/28/c-desmitificando-las-expresiones-lambda-y-iii.aspx</link><pubDate>Tue, 28 Apr 2009 21:40:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:147571</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=147571</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2009/04/28/c-desmitificando-las-expresiones-lambda-y-iii.aspx#comments</comments><description>&lt;div class="post-header-line-1"&gt;&lt;/div&gt;
&lt;div class="post-body entry-content"&gt;
&lt;p&gt;&lt;img src="http://3.bp.blogspot.com/_O9D62hXq-ng/SQtrgaCIm9I/AAAAAAAAA6k/XuuGqsiLjkw/s200/lambdas.jpg" alt="Lambda" border="0" id="BLOGGER_PHOTO_ID_5263418794000817106" style="margin:0px 0px 10px 10px;float:right;" /&gt;En el &lt;a href="http://www.variablenotfound.com/2009/03/c-desmitificando-las-expresiones-lambda.html"&gt;&lt;span style="color:#35537a;"&gt;primer post&lt;/span&gt;&lt;/a&gt; intentamos describir qu&amp;eacute; eran las expresiones lambda, resumiendo muy brevemente su utilidad, as&amp;iacute; como los aspectos sint&amp;aacute;cticos de este tipo de construcciones del lenguaje. &lt;a href="http://www.variablenotfound.com/2009/03/c-desmitificando-las-expresiones-lambda_29.html"&gt;&lt;span style="color:#35537a;"&gt;El segundo&lt;/span&gt;&lt;/a&gt; lo enfocamos a explicar el papel de las lambda como funciones an&amp;oacute;nimas, su estrecha relaci&amp;oacute;n con los delegados, y su forma de utilizaci&amp;oacute;n.&lt;br /&gt;&lt;br /&gt;En esta tercera y &amp;uacute;ltima entrega de la serie, vamos a centrarnos en otra de las grandes utilidades de las expresiones lambda en .NET framework: la definici&amp;oacute;n de &amp;aacute;rboles de expresi&amp;oacute;n.&lt;/p&gt;
&lt;h3 id="arboles"&gt;Las lambda como &amp;aacute;rboles de expresi&amp;oacute;n&lt;/h3&gt;
&lt;img src="http://3.bp.blogspot.com/_O9D62hXq-ng/SPD32TjLheI/AAAAAAAAA5w/9wlOhabJCs8/s400/ExpressionTree.jpg" alt="&amp;Aacute;rbol de expresi&amp;oacute;n" border="0" id="BLOGGER_PHOTO_ID_5255973277474194914" style="margin:0px 0px 10px 10px;float:right;" /&gt;Los compiladores de C# y VB.NET pueden, bajo determinadas circunstancias, utilizar las lambdas para crear un &amp;aacute;rbol de expresi&amp;oacute;n, una estructura en memoria que representa en forma de &amp;aacute;rbol las operaciones a realizar, y en el orden que hay que hacerlo, para lograr un objetivo. Si lo quer&amp;eacute;is ver m&amp;aacute;s claro, observad el diagrama adjunto, en el que se muestra el &amp;aacute;rbol de expresi&amp;oacute;n correspondiente a una funci&amp;oacute;n lambda que obtiene la media de dos n&amp;uacute;meros.&lt;br /&gt;&lt;br /&gt;Esto es muy diferente al caso anterior, donde habl&amp;aacute;bamos de las lambda como funciones ejecutables que pod&amp;iacute;an ser referenciadas por delegados e invocadas de forma directa. Entonces las expresiones lambda eran transformadas en tiempo de compilaci&amp;oacute;n en c&amp;oacute;digo ejecutable (de hecho, en m&amp;eacute;todos est&amp;aacute;ticos que pueden ser consultados usando &lt;a hreflang="en" href="http://www.red-gate.com/products/reflector/index.htm" title=".NET Reflector"&gt;Reflector&lt;/a&gt; u otros desensambladores), y por ello pod&amp;iacute;amos utilizarlas de forma directa.&lt;br /&gt;&lt;br /&gt;En el caso de los &amp;aacute;rboles de expresi&amp;oacute;n, la compilaci&amp;oacute;n no genera c&amp;oacute;digo ejecutable correspondiente a las instrucciones definidas en la lambda, sino el c&amp;oacute;digo para crear y llenar el &amp;aacute;rbol con dicha expresi&amp;oacute;n. Despu&amp;eacute;s, en tiempo de ejecuci&amp;oacute;n, ser&amp;aacute; posible recorrer dicho &amp;aacute;rbol, analizarlo, seriarlo para almacenarlo o moverlo a otras capas, e incluso compilarlo para poder lanzar su ejecuci&amp;oacute;n.&lt;br /&gt;&lt;br /&gt;Pero paremos aqu&amp;iacute; un momento... seg&amp;uacute;n lo dicho, cuando el compilador se encuentra con una expresi&amp;oacute;n lambda, por ejemplo &lt;code&gt;x =&amp;gt; x * 2&lt;/code&gt;, puede optar por generar una funci&amp;oacute;n an&amp;oacute;nima o por generar el c&amp;oacute;digo de llenado del &amp;aacute;rbol, &amp;iquest;c&amp;oacute;mo sabe lo que debe hacer?&lt;br /&gt;&lt;br /&gt;Pues bien, el compilador elegir&amp;aacute; la opci&amp;oacute;n adecuada dependiendo del tipo de la referencia a la expresi&amp;oacute;n lambda. Si se trata de un tipo de delegado como &lt;code&gt;Func&lt;/code&gt; o &lt;code&gt;Action&lt;/code&gt;, generar&amp;aacute; c&amp;oacute;digo ejecutable y las referencias a la funci&amp;oacute;n ser&amp;aacute;n tratados como delegados; si se usa el tipo &lt;code&gt;Expression&lt;/code&gt;, que veremos m&amp;aacute;s adelante, se generar&amp;aacute; el &amp;aacute;rbol de expresi&amp;oacute;n y las referencias no se considerar&amp;aacute;n delegados, sino objetos de este tipo. Por este motivo no podemos utilizar para declarar lambdas &lt;a href="http://www.variablenotfound.com/2007/12/variables-locales-implictamente-tipadas.html" title="Variables locales impl&amp;iacute;citamente tipadas en C#"&gt;&lt;span style="color:#35537a;"&gt;variables locales de tipo impl&amp;iacute;cito&lt;/span&gt;&lt;/a&gt;: el compilador no sabr&amp;iacute;a qu&amp;eacute; hacer.
&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  &lt;span style="color:red;font-weight:bold;"&gt;var dobla = a =&amp;gt; a * 2;&lt;/span&gt;&lt;span style="color:green;"&gt; // Error: no se puede asignar&lt;br /&gt;                          // una expresi&amp;oacute;n lambda a una variable&lt;br /&gt;                          // local de tipo impl&amp;iacute;cito.&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;
&lt;h3 id="definicionarboles"&gt;Definici&amp;oacute;n de &amp;aacute;rboles con expresiones lambda&lt;/h3&gt;
Para definir un &amp;aacute;rbol de expresi&amp;oacute;n a partir de una lambda debemos utilizar el tipo gen&amp;eacute;rico &lt;code&gt;Expression&amp;lt;TipoDelegado&amp;gt;&lt;/code&gt;, siendo &lt;code&gt;TipoDelegado&lt;/code&gt; un delegado como &lt;code&gt;Action&lt;/code&gt; o &lt;code&gt;Func&lt;/code&gt; de los descritos en el post anterior. &amp;iquest;Que esto os parece confuso? Pues esperad a ver el ejemplo... ;-)
&lt;pre&gt;&lt;code&gt;  Expression&amp;lt;&lt;span style="background-color:#ffffc0;"&gt;Func&amp;lt;int, int, int&amp;gt;&lt;/span&gt;&amp;gt; media = (a, b) =&amp;gt; (a + b) / 2;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;En realidad, aparte de lo dif&amp;iacute;cil de leer que es una declaraci&amp;oacute;n de este tipo, la idea es bastante sencilla. Lo que estamos indicando al compilador es que queremos montar un &amp;aacute;rbol de una expresi&amp;oacute;n de la que conocemos el tipo de los par&amp;aacute;metros de entrada y del valor de retorno, datos que indicamos mediante el delegado que utilizamos como argumento gen&amp;eacute;rico de la clase &lt;code&gt;Expression&lt;/code&gt;, la porci&amp;oacute;n que he marcado de amarillo en el ejemplo anterior. Adem&amp;aacute;s, este delegado lo utilizaremos cuando queramos convertir el &amp;aacute;rbol de expresi&amp;oacute;n en c&amp;oacute;digo ejecutable, m&amp;aacute;s adelante veremos c&amp;oacute;mo.&lt;br /&gt;&lt;br /&gt;Para que quede claro, ah&amp;iacute; van algunos ejemplos m&amp;aacute;s:
&lt;pre&gt;&lt;code&gt;  &lt;span style="color:green;"&gt;// &amp;Aacute;rbol de expresi&amp;oacute;n de una funci&amp;oacute;n que determina&lt;br /&gt;  // si el par&amp;aacute;metro que le llega es par&lt;/span&gt;&lt;br /&gt;  Expression&amp;lt;&lt;span style="background-color:#ffffc0;"&gt;Func&amp;lt;int, bool&amp;gt;&lt;/span&gt;&amp;gt; esPar = a =&amp;gt; a%2==0;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:green;"&gt;// &amp;Aacute;rbol de expresi&amp;oacute;n de una funci&amp;oacute;n &lt;br /&gt;  // que retorna el m&amp;aacute;ximo de dos n&amp;uacute;meros.&lt;/span&gt;&lt;br /&gt;  Expression&amp;lt;&lt;span style="background-color:#ffffc0;"&gt;Func&amp;lt;int, int, int&amp;gt;&lt;/span&gt;&amp;gt; maximo =&lt;br /&gt;              (a, b) =&amp;gt; a &amp;gt; b ? a:b;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:green;"&gt;// &amp;Aacute;rbol de expresi&amp;oacute;n de una funci&amp;oacute;n que&lt;br /&gt;  // retorna un string transformado&lt;/span&gt;&lt;br /&gt;  Expression&amp;lt;&lt;span style="background-color:#ffffc0;"&gt;Func&amp;lt;string, string&amp;gt;&lt;/span&gt;&amp;gt; TrimMays = &lt;br /&gt;              a =&amp;gt; a.Trim().ToUpper();&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:green;"&gt;// &amp;Aacute;rbol de expresi&amp;oacute;n de una acci&amp;oacute;n &lt;br /&gt;  // sin par&amp;aacute;metros que escribe por consola la fecha y hora.&lt;/span&gt;&lt;br /&gt;  Expression&amp;lt;&lt;span style="background-color:#ffffc0;"&gt;Action&lt;/span&gt;&amp;gt; accion =&lt;br /&gt;              () =&amp;gt; Console.WriteLine(DateTime.Now); &lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;Fijaos que el tipo de delegado &lt;code&gt;Action&lt;/code&gt; o &lt;code&gt;Func&lt;/code&gt;, que son los par&amp;aacute;metros gen&amp;eacute;ricos de la expresi&amp;oacute;n, son los que definen los tipos de par&amp;aacute;metros y retornos de la lambda. En el primer caso, el &lt;code&gt;Func&amp;lt;int, bool&amp;gt;&lt;/code&gt; define que la funci&amp;oacute;n recibe un entero y retorna un booleano; en el &amp;uacute;ltimo caso, ni se env&amp;iacute;a ni se recibe nada, de ah&amp;iacute; que utilicemos un delegado &lt;code&gt;Action&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Un detalle importante, antes de que se me olvide comentarlo. Los &amp;aacute;rboles de expresi&amp;oacute;n sirven, como su nombre indica, para almacenar expresiones. Esto limita el tipo de construcciones de c&amp;oacute;digo que podemos usar en las lambdas que los definen: no est&amp;aacute; permitido utilizar asignaciones, bloques con llaves { }, ni bucles... debe tratarse de una expresi&amp;oacute;n que pueda representarse en una jerarqu&amp;iacute;a de &amp;aacute;rbol. Si intentamos saltarnos estas restricciones, el compilador generar&amp;aacute; un error, aunque el tipo de delegado sea correcto y la funci&amp;oacute;n lambda tambi&amp;eacute;n, como en el siguiente ejemplo:&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;  &lt;span style="color:green;"&gt;// Suma los n primeros naturales&lt;/span&gt;&lt;br /&gt;  Expression&amp;lt;&lt;span style="background-color:#ffffc0;"&gt;Func&amp;lt;int, int&amp;gt;&lt;/span&gt;&amp;gt; expr =&lt;br /&gt;&lt;span style="color:red;"&gt;    n =&amp;gt; {&lt;br /&gt;           int t = 0;&lt;br /&gt;           for (int i = 1; i &amp;lt;= n; t += i++) ;&lt;br /&gt;           return t;&lt;br /&gt;         };&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:green;"&gt;// Error CS0834: Una expresi&amp;oacute;n lambda con cuerpo no puede ser &lt;br /&gt;  // convertida a &amp;aacute;rbol de expresi&amp;oacute;n&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;&lt;img src="http://2.bp.blogspot.com/_O9D62hXq-ng/SQ2ntSUN7eI/AAAAAAAAA7M/ZZ60FYYNyR8/s400/expression-tree-2.jpg" alt="&amp;Aacute;rbol de expresi&amp;oacute;n" border="0" id="BLOGGER_PHOTO_ID_5264047935918566882" style="margin:0px 0px 10px 10px;float:right;" /&gt;Volvemos un poco atr&amp;aacute;s ahora para recordar cuando comentaba que la compilaci&amp;oacute;n de una lambda no genera c&amp;oacute;digo ejecutable correspondiente a las instrucciones definidas en la expresi&amp;oacute;n, sino el c&amp;oacute;digo para llenar el &amp;aacute;rbol de expresi&amp;oacute;n que la representa. &lt;br /&gt;&lt;br /&gt;&amp;iquest;Y c&amp;oacute;mo hace eso? Muy sencillo. El compilador analiza la expresi&amp;oacute;n, genera la secuencia de instrucciones que compone el &amp;aacute;rbol, las compila, e introduce el resultado en el ensamblado. El siguiente ejemplo muestra c&amp;oacute;mo crear un &amp;aacute;rbol de expresi&amp;oacute;n usando una lambda, y una aproximaci&amp;oacute;n al c&amp;oacute;digo equivalente que genera el compilador, para que nos podamos hacer una idea del trabajo que nos ahorra esta caracter&amp;iacute;stica del lenguaje:&lt;br /&gt;
&lt;pre style="clear:both;"&gt;&lt;code&gt;&lt;br /&gt;  &lt;span style="color:green;"&gt;// &amp;Aacute;rbol definido con una lambda:&lt;/span&gt;&lt;br /&gt;  Expression&amp;lt;Func&amp;lt;int, bool&amp;gt;&amp;gt; esPar = a =&amp;gt; a % 2 == 0;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:green;"&gt;// Y el mismo &amp;aacute;rbol definido a mano, &lt;/span&gt;&lt;br /&gt;  &lt;span style="color:green;"&gt;// lo que genera el compilador autom&amp;aacute;ticamente:&lt;/span&gt;&lt;br /&gt;  ParameterExpression param = Expression.Parameter(typeof(int), &amp;quot;a&amp;quot;);&lt;br /&gt;  ConstantExpression dos = Expression.Constant(2, typeof(int));&lt;br /&gt;  ConstantExpression cero = Expression.Constant(0, typeof(int));&lt;br /&gt;  BinaryExpression modulo = Expression.Modulo(param, dos);&lt;br /&gt;  BinaryExpression comparacion = Expression.Equal(modulo, cero);&lt;br /&gt;  Expression&amp;lt;Func&amp;lt;int, bool&amp;gt;&amp;gt; esPar2 =&lt;br /&gt;       Expression.Lambda&amp;lt;Func&amp;lt;int, bool&amp;gt;&amp;gt;(comparacion, param);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;
&lt;h3 id="usoarboles"&gt;Uso de los &amp;aacute;rboles de expresi&amp;oacute;n&lt;/h3&gt;
Ya sabemos qu&amp;eacute; son los &amp;aacute;rboles de expresi&amp;oacute;n y c&amp;oacute;mo podemos definirlos, pero a&amp;uacute;n no le hemos visto sentido a su existencia. Pero lo tiene, vaya si lo tiene ;-)&lt;br /&gt;&lt;br /&gt;En primer lugar, el hecho de poder definir el &amp;aacute;rbol partiendo de una expresi&amp;oacute;n lambda, adem&amp;aacute;s de comodidad a la hora de codificar, nos permite aprovechar el tipado fuerte y la potencia del intellisense para evitar errores. En el ejemplo anterior, las probabilidades de que nos equivoquemos creando el &amp;aacute;rbol de forma manual son muy superiores a que ocurra si utilizamos la sintaxis lambda.&lt;br /&gt;&lt;br /&gt;Segundo, fijaos que en ning&amp;uacute;n momento se est&amp;aacute; generando c&amp;oacute;digo IL o compilando la expresi&amp;oacute;n representada por la lambda. Estamos creando una estructura en memoria. Esto quiere decir que despu&amp;eacute;s podemos procesar esta informaci&amp;oacute;n como estimemos conveniente; podemos, por ejemplo, analizar su contenido, recorrerlo, seriarlo, o transformarlo, en funci&amp;oacute;n de nuestras necesidades. Es ideal, por tanto, cuando tengamos inter&amp;eacute;s en interpretar una expresi&amp;oacute;n para realizar alguna acci&amp;oacute;n con ella.&lt;br /&gt;&lt;br /&gt;Vamos a ver ahora varios ejemplos para ilustrar el uso de las lambdas y &amp;aacute;rboles de expresi&amp;oacute;n en el mundo real.&lt;br /&gt;
&lt;h4&gt;Linq&lt;/h4&gt;
En el caso de &lt;acronym title="Language INtegrated Query"&gt;Linq&lt;/acronym&gt; aplicado a un proveedor externo de datos relacional (por ejemplo, las tecnolog&amp;iacute;as Linq to SQL, o Entity Framework), no tiene inter&amp;eacute;s alguno el c&amp;oacute;digo ejecutable asociado a una expresi&amp;oacute;n, sino su estructura, pues al final va a ser traducida al lenguaje o tecnolog&amp;iacute;a del almac&amp;eacute;n de informaci&amp;oacute;n. Supongamos la siguiente consulta para obtener los productos que comienzan por &amp;quot;S&amp;quot;:
&lt;pre&gt;&lt;code&gt;  &lt;span style="color:green;"&gt;// Usando una consulta Linq:&lt;/span&gt;&lt;br /&gt;  var datos = from p in productos &lt;br /&gt;                 where p.Nombre.StartsWith(&amp;quot;S&amp;quot;)&lt;br /&gt;                 select p;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:green;"&gt;// O su equivalente usando &lt;br /&gt;  // &lt;a href="http://www.variablenotfound.com/2008/04/chuleta-de-operadores-estndar-de.html" title="Operadores de consulta"&gt;&lt;span style="color:#35537a;"&gt;operadores de consulta&lt;/span&gt;&lt;/a&gt;:&lt;/span&gt;&lt;br /&gt;  var datos = productos.Where(&lt;span style="background-color:#ffffc0;"&gt;p=&amp;gt;p.Nombre.StartsWith(&amp;quot;S&amp;quot;)&lt;/span&gt;);&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;La lambda resaltada servir&amp;aacute; para crear un &amp;aacute;rbol de expresi&amp;oacute;n con las condiciones indicadas, pues el &lt;a href="http://www.variablenotfound.com/2008/02/mtodos-de-extensin-en-c.html" title="&amp;iquest;Qu&amp;eacute; son los m&amp;eacute;todos de extensi&amp;oacute;n?"&gt;&lt;span style="color:#35537a;"&gt;m&amp;eacute;todo de extensi&amp;oacute;n&lt;/span&gt;&lt;/a&gt; &lt;code&gt;Where&lt;/code&gt; aplicado acepta un predicado de tipo &lt;code&gt;Expression&lt;/code&gt;. No se genera ning&amp;uacute;n m&amp;eacute;todo an&amp;oacute;nimo para la expresi&amp;oacute;n lambda, ni se traduce a IL su contenido: s&amp;oacute;lo interesa para definir la expresi&amp;oacute;n que ser&amp;aacute; introducida en el &amp;aacute;rbol. M&amp;aacute;s adelante, en el momento de extraer realmente la informaci&amp;oacute;n desde el almac&amp;eacute;n correspondiente, el componente proveedor de datos recorrer&amp;aacute; y analizar&amp;aacute; la estructura en memoria, generando su equivalente en SQL, que es lo que lanzar&amp;aacute; al &lt;acronym title="Sistema Gestor de Bases de Datos"&gt;SGBD&lt;/acronym&gt; para obtener los datos.&lt;br /&gt;&lt;br /&gt;Por cierto, existen en la actualidad una gran cantidad de &lt;a hreflang="en" href="http://blogs.msdn.com/charlie/archive/2008/02/28/link-to-everything-a-list-of-linq-providers.aspx" title="Lista de proveedores Linq"&gt;proveedores de Linq&lt;/a&gt;, capaces de transformar los &amp;aacute;rboles de expresi&amp;oacute;n en consultas a casi cualquier tipo de almac&amp;eacute;n. Fijaos que la posibilidad de separar la codificaci&amp;oacute;n lambda de la interpretaci&amp;oacute;n de la expresi&amp;oacute;n hace posible su utilizaci&amp;oacute;n en una gran variedad de &amp;aacute;mbitos.&lt;br /&gt;&lt;br /&gt;
&lt;h4&gt;C&amp;aacute;lculo simb&amp;oacute;lico&lt;/h4&gt;
Otro ejemplo que ilustra muy bien las posibilidades de los &amp;aacute;rboles de expresi&amp;oacute;n, de mano del maestro &lt;a href="http://geeks.ms/blogs/ohernandez" title="Octavio Hern&amp;aacute;ndez, en Geeks.ms"&gt;&lt;span style="color:#35537a;"&gt;Octavio Hern&amp;aacute;ndez&lt;/span&gt;&lt;/a&gt;. Se trata del art&amp;iacute;culo &lt;a href="http://www.elguille.info/NET/futuro/firmas_octavio_calculo_simbolico.htm" title="C&amp;aacute;lculo simb&amp;oacute;lico en C# 3.0"&gt;&lt;span style="color:#35537a;"&gt;C&amp;aacute;lculo simb&amp;oacute;lico en C# 3.0&lt;/span&gt;&lt;/a&gt;, publicado en la web de &lt;a href="http://www.elguille.info/" title="El Guille"&gt;&lt;span style="color:#35537a;"&gt;El Guille&lt;/span&gt;&lt;/a&gt; a principios de 2007.&lt;br /&gt;&lt;br /&gt;A lo largo del art&amp;iacute;culo se realiza la implementaci&amp;oacute;n b&amp;aacute;sica de un sistema de c&amp;aacute;lculo de derivadas de funciones matem&amp;aacute;ticas partiendo de un &amp;aacute;rbol de expresiones. El proceso, que el autor va explicando paso a paso, consiste en analizar el &amp;aacute;rbol, e ir generando otro &amp;aacute;rbol con el resultado de la derivaci&amp;oacute;n de cada expresi&amp;oacute;n encontrada. A continuaci&amp;oacute;n se muestra la porci&amp;oacute;n de c&amp;oacute;digo donde se realiza la derivaci&amp;oacute;n de una operaci&amp;oacute;n de suma, utilizando recursividad para derivar adem&amp;aacute;s cada uno de los sumandos:
&lt;pre&gt;&lt;code&gt;  private static Expression Derive(this Expression e, string paramName)&lt;br /&gt;  {&lt;br /&gt;      switch (e.NodeType)&lt;br /&gt;      {&lt;br /&gt;          [...]&lt;br /&gt;          &lt;span style="color:green;"&gt;// sum rule&lt;/span&gt;&lt;br /&gt;          case ExpressionType.Add:&lt;br /&gt;              {&lt;br /&gt;                  Expression dleft = &lt;br /&gt;                     ((BinaryExpression) e).Left.Derive(paramName);&lt;br /&gt;                  Expression dright = &lt;br /&gt;                     ((BinaryExpression) e).Right.Derive(paramName);&lt;br /&gt;                  return Expression.Add(dleft, dright);&lt;br /&gt;              }&lt;br /&gt;          [...]&lt;br /&gt;      }&lt;br /&gt;  }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;Al final, fijaos que de nuevo no nos interesa en absoluto la lambda como funci&amp;oacute;n an&amp;oacute;nima ni delegado, sino la estructura de la propia expresi&amp;oacute;n, de forma que podamos recorrerla y transformarla en otra expresi&amp;oacute;n, en este caso la funci&amp;oacute;n derivada de la original. El siguiente ejemplo muestra el uso de esta clase:
&lt;pre&gt;&lt;code&gt;   Expression&amp;lt;Func&amp;lt;double, double&amp;gt;&amp;gt; &lt;br /&gt;                funcion = x =&amp;gt; x*x;          &lt;span style="color:green;"&gt;// f(x)=x^2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  Expression&amp;lt;Func&amp;lt;double, double&amp;gt;&amp;gt; &lt;br /&gt;                derivada = funcion.Derive(); &lt;span style="color:green;"&gt;// f&amp;#39;(x)=2*x&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  Console.WriteLine(derivada); &lt;span style="color:green;"&gt;// Muestra la funci&amp;oacute;n derivada:&lt;br /&gt;                               //    x =&amp;gt; ((x * 1) + (1 * x))&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;Creedme, vale la pena &lt;a href="http://www.elguille.info/NET/futuro/firmas_octavio_calculo_simbolico.htm" title="C&amp;aacute;lculo simb&amp;oacute;lico en C# 3.0"&gt;&lt;span style="color:#35537a;"&gt;echarle un vistazo&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;
&lt;h4&gt;ASP.NET MVC&lt;/h4&gt;
Un &amp;uacute;ltimo ejemplo, que demuestra la versatilidad del uso de lambdas y &amp;aacute;rboles de expresi&amp;oacute;n en multitud de escenarios. En el &lt;a href="http://www.asp.net/mvc" title="Sitio oficial de ASP.NET MVC"&gt;&lt;span style="color:#35537a;"&gt;framework ASP.NET MVC&lt;/span&gt;&lt;/a&gt;, es posible crear enlaces hacia acciones desde dentro de las vistas (p&amp;aacute;ginas .ASPX), que no son sino m&amp;eacute;todos dentro de unas clases concretas llamadas &amp;quot;controladores&amp;quot;. El caso es que para hacer referencia a un m&amp;eacute;todo del controlador, pueden utilizarse estas dos v&amp;iacute;as, de resultado id&amp;eacute;ntico:
&lt;pre&gt;&lt;code&gt;  &lt;span style="color:green;"&gt;// Obtiene un enlace al m&amp;eacute;todo &amp;quot;ChangePassword&amp;quot;&lt;br /&gt;  // de la clase &amp;quot;AccountController&amp;quot;:&lt;/span&gt;&lt;br /&gt;  Html.ActionLink(&amp;quot;Cambiar clave&amp;quot;, &amp;quot;ChangePassword&amp;quot;, &amp;quot;Account&amp;quot;)&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:green;"&gt;// Lo mismo, pero usando un &amp;aacute;rbol de expresi&amp;oacute;n:&lt;/span&gt;&lt;br /&gt;  Html.ActionLink&amp;lt;AccountController&amp;gt;&lt;br /&gt;              (acc=&amp;gt;acc.ChangePassword(), &amp;quot;Cambiar clave&amp;quot;)&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;Aunque el resultado es el mismo, la segunda usa un &amp;aacute;rbol de expresi&amp;oacute;n para realizar la referencia al m&amp;eacute;todo &lt;code&gt;ChangePassword&lt;/code&gt; de la clase &lt;code&gt;AccountController&lt;/code&gt;. La implementaci&amp;oacute;n del m&amp;eacute;todo &lt;code&gt;ActionLink&lt;/code&gt; recorre el &amp;aacute;rbol generado desde la expresi&amp;oacute;n lambda para obtener el nombre del controlador y del m&amp;eacute;todo, por lo que es equivalente a primera f&amp;oacute;rmula, pero benefici&amp;aacute;ndose de las ventajas del tipado fuerte y del &lt;em&gt;intellisense&lt;/em&gt; en la edici&amp;oacute;n.&lt;br /&gt;
&lt;h3&gt;Los &amp;aacute;rboles de expresi&amp;oacute;n como c&amp;oacute;digo ejecutable&lt;/h3&gt;
Hasta ahora siempre me he referido a los &amp;aacute;rboles de expresi&amp;oacute;n como entidades de almacenamiento. De alguna u otra forma, estaba equiparando su utilidad a la cualquier estructura de datos que permitiera guardar y procesar informaci&amp;oacute;n, lo cual es cierto pero s&amp;oacute;lo parcialmente.&lt;br /&gt;&lt;br /&gt;Los &amp;aacute;rboles de expresi&amp;oacute;n aportan una caracter&amp;iacute;stica adicional: se pueden convertir en c&amp;oacute;digo ejecutable. Es decir, &lt;strong&gt;es posible compilar un &amp;aacute;rbol de expresi&amp;oacute;n&lt;/strong&gt; en tiempo de ejecuci&amp;oacute;n, dando lugar a una funci&amp;oacute;n an&amp;oacute;nima a la que podemos tener acceso, es decir, invocarla, a trav&amp;eacute;s de sus delegados.&lt;br /&gt;&lt;br /&gt;Ve&amp;aacute;moslo con un caso concreto. Retomando el ejemplo de obtenci&amp;oacute;n de derivadas, ser&amp;iacute;a perfectamente posible obtener el valor de la funci&amp;oacute;n derivada en un punto ampliando ligeramente el c&amp;oacute;digo visto anteriormente:
&lt;pre&gt;&lt;code&gt;  Expression&amp;lt;Func&amp;lt;double, double&amp;gt;&amp;gt; &lt;br /&gt;                funcion = x =&amp;gt; x*x;          &lt;span style="color:green;"&gt;// f(x)=x^2&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  Expression&amp;lt;Func&amp;lt;double, double&amp;gt;&amp;gt; &lt;br /&gt;                derivada = funcion.Derive(); &lt;span style="color:green;"&gt;// f&amp;#39;(x)=2*x&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:green;"&gt;// Compilamos la funci&amp;oacute;n derivada&lt;br /&gt;  // y obtenemos un delegado a la misma:&lt;/span&gt;&lt;br /&gt;  Func&amp;lt;double, double&amp;gt; funcDerivada = derivada.Compile();&lt;br /&gt;&lt;br /&gt;  double result = funcDerivada(6); &lt;span style="color:green;"&gt;// Obtenemos el valor de la funci&amp;oacute;n &lt;br /&gt;                                   // invocando al delegado con x=6&lt;/span&gt;&lt;br /&gt;  Console.WriteLine(result);       &lt;span style="color:green;"&gt;// Muestra &amp;quot;12&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;Como se puede observar en el c&amp;oacute;digo, la llamada al m&amp;eacute;todo &lt;code&gt;Compile()&lt;/code&gt; devuelve un delegado del tipo &lt;code&gt;Func&lt;/code&gt; indicado en el par&amp;aacute;metro gen&amp;eacute;rico de la expresi&amp;oacute;n, que apunta hacia la funci&amp;oacute;n an&amp;oacute;nima creada &amp;quot;al vuelo&amp;quot; a partir de las expresiones contenidas en el &amp;aacute;rbol. Es decir, desde la definici&amp;oacute;n simb&amp;oacute;lica contenida en el &amp;aacute;rbol &amp;iexcl;obtenemos c&amp;oacute;digo ejecutable!&lt;br /&gt;&lt;br /&gt;Aunque espectacular, en realidad no hay nada m&amp;aacute;gico en esta caracter&amp;iacute;stica: se trata de ir recorriendo el &amp;aacute;rbol y emitiendo el c&amp;oacute;digo IL correspondiente a cada expresi&amp;oacute;n, que est&amp;aacute; perfectamente tipificada y definida. En el namespace &lt;code&gt;System.Linq.Expressions&lt;/code&gt; existe una bonita clase interna llamada &lt;code&gt;ExpressionCompiler&lt;/code&gt; que se dedica exclusivamente a ello, utilizando herramientas suministradas por &lt;code&gt;System.Reflection.Emit&lt;/code&gt;, como los generadores de lenguaje intermedio &lt;code&gt;ILGenerator&lt;/code&gt;.&lt;br /&gt;
&lt;h3&gt;&amp;iexcl;Y hasta aqu&amp;iacute; hemos llegado!&lt;/h3&gt;
A lo largo de estos tres posts hemos recorrido las principales caracter&amp;iacute;sticas y utilidades de las expresiones lambda. Obviamente, han quedado cosas por detr&amp;aacute;s; no era objetivo de esta serie profundizar demasiado, sino ofrecer una visi&amp;oacute;n suficiente para animar a los desarrolladores a utilizar esta potente caracter&amp;iacute;stica que nos ofrece C# (y VB.NET).&lt;br /&gt;&lt;br /&gt;Espero que os haya sido una lectura &amp;uacute;til, al menos tanto como me ha resultado a m&amp;iacute; su escritura. Ah, y para consultas, sugerencias o puntualizaciones, por aqu&amp;iacute; me ten&amp;eacute;is.&lt;br /&gt;&lt;br /&gt;Publicado en: &lt;a href="http://www.variablenotfound.com"&gt;&lt;span style="color:#35537a;"&gt;www.variablenotfound.com&lt;/span&gt;&lt;/a&gt;. &lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=147571" 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/vs2008/default.aspx">vs2008</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/linq/default.aspx">linq</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/_26002300_225_3B00_rboles+de+expresi_26002300_243_3B00_n/default.aspx">&amp;#225;rboles de expresi&amp;#243;n</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/lambdas/default.aspx">lambdas</category></item><item><title>C#: Desmitificando las expresiones lambda (II)</title><link>http://geeks.ms/blogs/jmaguilar/archive/2009/04/21/c-desmitificando-las-expresiones-lambda-ii.aspx</link><pubDate>Tue, 21 Apr 2009 21:54:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:147071</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=147071</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2009/04/21/c-desmitificando-las-expresiones-lambda-ii.aspx#comments</comments><description>&lt;div class="post-body entry-content"&gt;&lt;span&gt;
&lt;div class="post-header-line-1"&gt;&lt;/div&gt;
&lt;div class="post-body entry-content"&gt;
&lt;p&gt;&lt;img src="http://3.bp.blogspot.com/_O9D62hXq-ng/SQtrgaCIm9I/AAAAAAAAA6k/XuuGqsiLjkw/s200/lambdas.jpg" alt="Lambda" border="0" id="BLOGGER_PHOTO_ID_5263418794000817106" style="margin:0px 0px 10px 10px;float:right;" /&gt;En el &lt;a href="http://www.variablenotfound.com/2009/03/c-desmitificando-las-expresiones-lambda.html"&gt;&lt;span style="color:#35537a;"&gt;post anterior&lt;/span&gt;&lt;/a&gt; intentamos realizar una primera aproximaci&amp;oacute;n a las expresiones lambda, centr&amp;aacute;ndonos en obtener una definici&amp;oacute;n lo suficientemente cercana, que nos permitiera conocer a grandes rasgos qu&amp;eacute; son, as&amp;iacute; como en describir su forma general y sus particularidades sint&amp;aacute;cticas.&lt;br /&gt;&lt;br /&gt;En esta segunda entrega vamos a profundizar un poco en el papel de las expresiones lambda como v&amp;iacute;a para definir muy r&amp;aacute;pidamente funciones an&amp;oacute;nimas y los tipos de delegados con los que podemos referenciarlas, y por tanto, invocarlas.&lt;br /&gt;&lt;br /&gt;Ya en el tercer post describiremos el papel de las &lt;a href="http://www.variablenotfound.com/2009/03/c-desmitificando-las-expresiones-lambda_2829.html"&gt;&lt;span style="color:#35537a;"&gt;expresiones lambda como herramienta de generaci&amp;oacute;n de &amp;aacute;rboles de expresi&amp;oacute;n&lt;/span&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="funciones"&gt;Las lambdas como funciones an&amp;oacute;nimas&lt;/h3&gt;
Como hab&amp;iacute;amos insinuado anteriormente, uno de los usos de las expresiones lambda es permitir la definici&amp;oacute;n &amp;quot;en l&amp;iacute;nea&amp;quot; de funciones an&amp;oacute;nimas. De hecho, en tiempo de compilaci&amp;oacute;n las expresiones lambda son convertidas en m&amp;eacute;todos a los que el compilador establece un nombre &amp;uacute;nico autogenerado, como los ejemplos mostrados a continuaci&amp;oacute;n:&lt;br /&gt;&lt;br /&gt;&lt;img src="http://1.bp.blogspot.com/_O9D62hXq-ng/SQww-8_vZJI/AAAAAAAAA68/qPY91CUBI8s/s400/lambda-anonimas.jpg" alt="Transformaci&amp;oacute;n de lamdas en m&amp;eacute;todos" border="0" id="BLOGGER_PHOTO_ID_5263635922572764306" style="text-align:center;margin:0px auto 10px;display:block;" /&gt;&lt;br /&gt;Las referencias a estas funciones an&amp;oacute;nimas son transformadas en delegados (punteros) a las mismas, lo que nos permitir&amp;aacute;, por ejemplo, invocarlas desde el c&amp;oacute;digo. En la pr&amp;aacute;ctica esto quiere decir que podemos asignar una lambda a una variable y ejecutarla como muestra el siguiente pseudoc&amp;oacute;digo:
&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  delegado &lt;strong&gt;duplica&lt;/strong&gt; = &lt;span style="background-color:#ffffc0;"&gt;x =&amp;gt; x * 2&lt;/span&gt;; &lt;br /&gt;  escribe &lt;strong&gt;duplica(2)&lt;/strong&gt;; &lt;span style="color:green;"&gt;// Escribe un 4&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;En este primer acercamiento, fijaos que &lt;code&gt;duplica&lt;/code&gt; es el nombre del delegado, la funci&amp;oacute;n definida en forma de expresi&amp;oacute;n lambda no tiene nombre, ser&amp;aacute; el compilador el que se asigne uno. &lt;br /&gt;&lt;br /&gt;Veamos c&amp;oacute;mo se concreta esta idea en C#. En el siguiente c&amp;oacute;digo, la variable &lt;code&gt;duplica&lt;/code&gt; &lt;em&gt;apunta&lt;/em&gt; hacia una funci&amp;oacute;n an&amp;oacute;nima definida a trav&amp;eacute;s de la expresi&amp;oacute;n lambda en cuya implementaci&amp;oacute;n lo &amp;uacute;nico que se hace es retornar el doble del valor que le llega como par&amp;aacute;metro. Vemos tambi&amp;eacute;n c&amp;oacute;mo podemos utilizarla de forma directa:
&lt;pre&gt;&lt;code&gt;  Func&amp;lt;int, int&amp;gt; &lt;strong&gt;duplica &lt;/strong&gt;= &lt;span style="background-color:#ffffc0;"&gt;x =&amp;gt; x * 2&lt;/span&gt;;&lt;br /&gt;  int result = &lt;strong&gt;duplica&lt;/strong&gt;(7); &lt;span style="color:green;"&gt;// result vale 14&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;S&amp;oacute;lo con objeto de que pod&amp;aacute;is entender el c&amp;oacute;digo anterior, os adelantar&amp;eacute; que la porci&amp;oacute;n &lt;code&gt;Func&amp;lt;int, int&amp;gt;&lt;/code&gt; es una forma r&amp;aacute;pida de tipificar el delegado, indicando que &lt;code&gt;duplica&lt;/code&gt; apunta a una funci&amp;oacute;n que espera un entero como par&amp;aacute;metro de entrada, y que su valor de retorno ser&amp;aacute; otro entero. Esto lo veremos dentro de un momento.&lt;br /&gt;&lt;br /&gt;De la misma forma que asignamos la expresi&amp;oacute;n lambda a una variable, podemos hacerlo tambi&amp;eacute;n para indicar el valor de un par&amp;aacute;metro a un m&amp;eacute;todo que acepte un delegado concreto. Por ejemplo, el siguiente c&amp;oacute;digo muestra un m&amp;eacute;todo llamado &lt;code&gt;calcula&lt;/code&gt; que recibe un valor entero y una referencia a una funci&amp;oacute;n, retornando el resultado de efectuar dicha operaci&amp;oacute;n sobre el entero proporcionado:
&lt;pre&gt;&lt;code&gt;  &lt;span style="color:green;"&gt;// Es m&amp;eacute;todo ejecuta la funci&amp;oacute;n indicada por&lt;br /&gt;  // el par&amp;aacute;metro &lt;em&gt;operacion&lt;/em&gt;, envi&amp;aacute;ndole el &lt;em&gt;valor&lt;/em&gt; especificado, &lt;br /&gt;  // y retorna el resultado obtenido de la misma.&lt;/span&gt;&lt;br /&gt;  public int calcula(int valor, Func&amp;lt;int, int&amp;gt; operacion)&lt;br /&gt;  {&lt;br /&gt;    return operacion(valor); &lt;span style="color:green;"&gt;// retorna el resultado de aplicar la &lt;br /&gt;                             // expresi&amp;oacute;n indicada al valor.&lt;/span&gt;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:green;"&gt;// Usos posibles:&lt;/span&gt;&lt;br /&gt;  int i = calcula(4, &lt;span style="background-color:#ffffc0;"&gt;x =&amp;gt; x / 2&lt;/span&gt;); &lt;span style="color:green;"&gt;// Le pasamos una referencia a la &lt;br /&gt;                                  // funci&amp;oacute;n que estamos definiendo sobre&lt;br /&gt;                                  // la marcha. El resultado es que i=2.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  int j = calcula(4, &lt;strong&gt;duplica&lt;/strong&gt;);    &lt;span style="color:green;"&gt;// Le pasamos la variable &amp;quot;duplica&amp;quot;, &lt;br /&gt;                                  // que es una referencia a la lambda&lt;br /&gt;                                  // definida anteriormente. J valdr&amp;aacute; 8.&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;
&lt;div style="background-color:#fffff0;margin-left:4em;border:#c0c0c0 1px dotted;padding:5px;"&gt;&amp;lt;HistoriaDelAbuelete&amp;gt;&lt;br /&gt;Seguro que a los m&amp;aacute;s viejos del lugar esto le recuerda a los &lt;a hreflang="en" href="http://www.leylan.com/app.asp?pg=blocks" title="They&amp;#39;re Mysterious... They&amp;#39;re Code Blocks"&gt;Codeblocks&lt;/a&gt; que utiliz&amp;aacute;bamos en &lt;a href="http://es.wikipedia.org/wiki/Clipper_(lenguaje_de_programaci%C3%B3n)" title="El Lenguaje Clipper"&gt;&lt;span style="color:#35537a;"&gt;Clipper&lt;/span&gt;&lt;/a&gt; a principios de los 90 (uuf, c&amp;oacute;mo pasa el tiempo...). &amp;iquest;Todav&amp;iacute;a reconoc&amp;eacute;is el siguiente c&amp;oacute;digo?
&lt;pre&gt;&lt;code&gt;  bDuplica := { |n| n*2 }&lt;br /&gt;  ? EVAL(bDuplica, 7)     // Muestra un 14&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&amp;lt;/HistoriaDelAbuelete&amp;gt;&lt;/div&gt;
&lt;br /&gt;Una consecuencia directa de que las expresiones lambdas sean referenciadas a trav&amp;eacute;s de delegados es que &lt;strong&gt;podemos utilizarlas en cualquier sitio donde se acepte un delegado&lt;/strong&gt;, con la &amp;uacute;nica precauci&amp;oacute;n de escribirla teniendo en cuenta el tipo de su retorno y los par&amp;aacute;metros que recibe. Un ejemplo claro lo tenemos en la suscripci&amp;oacute;n a eventos, donde la t&amp;eacute;cnica habitual consiste en utilizar un delegado a un m&amp;eacute;todo en el que se implementa la l&amp;oacute;gica del tratamiento de los mismos, algo como:&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;  &lt;span style="color:green;"&gt;// Nos suscribimos al evento MouseMove:&lt;/span&gt;&lt;br /&gt;  this.MouseMove += &lt;span style="background-color:#ffffc0;"&gt;new MouseEventHandler(this.Form1_MouseMove);&lt;/span&gt;&lt;br /&gt;  [...]&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:green;"&gt;// Tratamiento del evento MouseMove:&lt;/span&gt;&lt;br /&gt;  private void Form1_MouseMove(object sender, MouseEventArgs e)&lt;br /&gt;  {&lt;br /&gt;    this.Text = e.X + &amp;quot;,&amp;quot; + e.Y;&lt;br /&gt;  }&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;Como sabemos, podemos suscribirnos al evento &lt;code&gt;MouseMove&lt;/code&gt; a&amp;ntilde;adi&amp;eacute;ndole delegados del tipo &lt;code&gt;MouseEventHandler&lt;/code&gt;, definido en &lt;code&gt;System.Windows.Forms&lt;/code&gt;, cuya firma indica que recibe un par&amp;aacute;metro de tipo &lt;code&gt;object&lt;/code&gt;, otro de tipo &lt;code&gt;MouseEventArgs&lt;/code&gt; y no retorna ning&amp;uacute;n valor, exactamente igual que ser&amp;iacute;a un delegado an&amp;oacute;nimo (C# 2.0) escrito as&amp;iacute;:&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;  this.MouseMove += delegate(object sender, MouseEventArgs args)&lt;br /&gt;  {&lt;br /&gt;    this.Text = args.X + &amp;quot;,&amp;quot; + args.Y;&lt;br /&gt;  };&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;Y dado que las lambdas pueden sustituir de forma directa a cualquier delegado, podemos utilizarlas para conseguir un c&amp;oacute;digo m&amp;aacute;s compacto:&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;  this.MouseMove += &lt;span style="background-color:#ffffc0;"&gt;(sender, args) =&amp;gt; {&lt;/span&gt;&lt;br /&gt;                    &lt;span style="background-color:#ffffc0;"&gt;   this.Text = args.X + &amp;quot;,&amp;quot; + args.Y;&lt;/span&gt;&lt;br /&gt;                    &lt;span style="background-color:#ffffc0;"&gt;};&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;Llegados a este punto es conveniente aclarar que las expresiones lambda son caracter&amp;iacute;sticas introducidas en los lenguajes, y por tanto en sus compiladores, pero no en la plataforma de ejecuci&amp;oacute;n (CLR) en s&amp;iacute;. Por tanto, todo lo descrito hasta el momento era posible realizarlo antes que las lambda aparecieran por el horizonte, aunque de forma un poco m&amp;aacute;s tediosa, utilizando mecanismos que la versi&amp;oacute;n 2.0 del framework pon&amp;iacute;a a nuestra disposici&amp;oacute;n, como los delegados y m&amp;eacute;todos an&amp;oacute;nimos. En este sentido, el uso de expresiones lambda aportan mucha simplicidad, elegancia y legibilidad al c&amp;oacute;digo.&lt;br /&gt;&lt;br /&gt;Esto explica, adem&amp;aacute;s, que Visual Studio 2008 sea capaz de generar c&amp;oacute;digo para .NET 2.0 a partir de c&amp;oacute;digo fuente C# 3.0.&lt;br /&gt;&lt;br /&gt;
&lt;h3 id="tiposdelegados"&gt;Tipos de delegados de expresiones lambda&lt;/h3&gt;
Antes ya hab&amp;iacute;a adelantado que la definici&amp;oacute;n &lt;code&gt;Func&amp;lt;int, int&amp;gt;&lt;/code&gt; era simplemente una forma de indicar el tipo del par&amp;aacute;metro que recib&amp;iacute;a la funci&amp;oacute;n lambda, as&amp;iacute; como el tipo del valor de retorno. En realidad, lo &amp;uacute;nico que est&amp;aacute;bamos haciendo era definir, de forma muy sencilla y r&amp;aacute;pida, el delegado hacia la funci&amp;oacute;n. &lt;br /&gt;&lt;br /&gt;Vamos a concretar esto un poco m&amp;aacute;s, pero antes de continuar, una cosa: si para t&amp;iacute; un gen&amp;eacute;rico es un &lt;a href="http://es.wikipedia.org/wiki/Medicamento_gen%C3%A9rico" title="Medicamentos gen&amp;eacute;ricos en la Wikipedia"&gt;&lt;span style="color:#35537a;"&gt;tipo de medicamento&lt;/span&gt;&lt;/a&gt;, mejor que leas algo sobre el tema antes de continuar, pues en caso contrario es posible que te pierdas un poco ;-). Pues probar leyendo una &lt;a href="http://www.variablenotfound.com/2007/03/generics-en-c.html" title="Introducci&amp;oacute;n a los generics"&gt;&lt;span style="color:#35537a;"&gt;introducci&amp;oacute;n a los generics en c#&lt;/span&gt;&lt;/a&gt;, o la &lt;a href="http://msdn.microsoft.com/es-es/library/512aeb7t(VS.80).aspx" title="Tipos gen&amp;eacute;ricos"&gt;&lt;span style="color:#35537a;"&gt;Gu&amp;iacute;a de programaci&amp;oacute;n de C#&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;.NET Framework ofrece en el espacio de nombres &lt;code&gt;System&lt;/code&gt; un conjunto de definiciones de gen&amp;eacute;ricas de delegados para que podamos utilizarlos para &amp;quot;apuntar&amp;quot; hacia las funciones definidas mediante expresiones lambda, llamados &lt;code&gt;Action&lt;/code&gt; y &lt;code&gt;Func&lt;/code&gt;.&lt;br /&gt;&lt;br /&gt;Utilizaremos los tipos &lt;code&gt;Func&lt;/code&gt; para definir referencias a expresiones lambda que retornen un valor, o sea, funciones. De ah&amp;iacute; su nombre. Los tipos &lt;code&gt;Action&lt;/code&gt;, en cambio, est&amp;aacute;n destinados a referenciar a lambdas que realicen acciones y que no retornen ning&amp;uacute;n valor. De ah&amp;iacute; su nombre tambi&amp;eacute;n. ;-)&lt;br /&gt;&lt;br /&gt;Una de estas definiciones es la que hab&amp;iacute;amos usado en un ejemplo anterior:
&lt;pre&gt;&lt;code&gt;  &lt;span style="background-color:#ffffc0;"&gt;&lt;strong&gt;Func&amp;lt;int, int&amp;gt;&lt;/strong&gt;&lt;/span&gt; duplica = x =&amp;gt; x * 2;&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;Como se puede observar, al tratarse de una referencia a una funci&amp;oacute;n que retorna un valor, hemos utilizado un tipo &lt;code&gt;Func&lt;/code&gt; con dos par&amp;aacute;metros gen&amp;eacute;ricos, que corresponde con la siguiente declaraci&amp;oacute;n existente en el espacio de nombres &lt;code&gt;System&lt;/code&gt;:&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;  public delegate TResult Func&amp;lt;T, TResult&amp;gt;(T arg);&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;Por ello, cuando declar&amp;aacute;bamos que la variable &lt;code&gt;duplica&lt;/code&gt; era del tipo &lt;code&gt;Func&amp;lt;int, int&amp;gt;&lt;/code&gt;, lo que indic&amp;aacute;bamos era, en primer lugar que el par&amp;aacute;metro que necesitaba la lambda era un &lt;code&gt;int&lt;/code&gt;, y que &amp;eacute;sta nos devolver&amp;iacute;a tambi&amp;eacute;n un &lt;code&gt;int&lt;/code&gt;, es decir, lo mismo que si hubi&amp;eacute;ramos definido &lt;code&gt;duplica&lt;/code&gt; as&amp;iacute;, utilizando m&amp;eacute;todos an&amp;oacute;nimos de C# 2.0:&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;  &lt;span style="color:green;"&gt;// En el &amp;aacute;rea de declaraciones:&lt;/span&gt;&lt;br /&gt;  public delegate int Duplicador(int arg);&lt;br /&gt;  &lt;span style="color:blue;"&gt;...&lt;/span&gt;&lt;br /&gt;  &lt;span style="color:green;"&gt;// En el c&amp;oacute;digo:&lt;/span&gt;&lt;br /&gt;  Duplicador duplica = delegate(int k) { return k*2 };&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;Obviamente, la sintaxis lambda es mucho m&amp;aacute;s compacta y expresiva.&lt;br /&gt;&lt;br /&gt;En la pr&amp;aacute;ctica, lo &amp;uacute;nico que tenemos que tener claro a la hora de referenciar una funci&amp;oacute;n lambda es el tipo de cada uno de los par&amp;aacute;metros que usa, y el tipo de retorno. Estos se introducen, en ese orden, en los par&amp;aacute;metros gen&amp;eacute;ricos de la clase &lt;code&gt;Func&lt;/code&gt; y listo. Como esto debe quedar claro, ah&amp;iacute; van unos ejemplos de definici&amp;oacute;n y uso:
&lt;pre&gt;&lt;code&gt;  &lt;span style="color:green;"&gt;// Recibe un entero y retorna un booleano:&lt;/span&gt;&lt;br /&gt;  Func&amp;lt;int, bool&amp;gt; esPar = x =&amp;gt; x%2==0;     &lt;br /&gt;  Console.WriteLine(esPar(2)); &lt;span style="color:green;"&gt;// Muestra &amp;quot;True&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:green;"&gt;// Recibe dos enteros, retorna otro entero:&lt;/span&gt;&lt;br /&gt;  Func&amp;lt;int, int, int&amp;gt; suma = (a,b) =&amp;gt; a+b;&lt;br /&gt;  Console.WriteLine(suma(2,3)); &lt;span style="color:green;"&gt;// Muestra &amp;quot;5&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:green;"&gt;// No recibe nada, retorna un texto:&lt;/span&gt;&lt;br /&gt;  Func&amp;lt;string&amp;gt; hora = () =&amp;gt; &amp;quot;Son las &amp;quot;&lt;br /&gt;                             + DateTime.Now.ToShortTimeString();&lt;br /&gt;  Console.WriteLine(hora()); &lt;span style="color:green;"&gt;// Muestra &amp;quot;Son las 14:21:10&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;Es importante saber que en el framework est&amp;aacute;n definidos los delegados &lt;code&gt;Func&amp;lt;tipo1, tipo2..., tipoResult&amp;gt;&lt;/code&gt; para funciones de hasta cuatro par&amp;aacute;metros. Si necesitamos m&amp;aacute;s deberemos definir los delegados a mano, aunque esto es realmente sencillo utilizando una de las declaraciones existentes y a&amp;ntilde;adi&amp;eacute;ndole el n&amp;uacute;mero de par&amp;aacute;metros que deseemos. Por ejemplo, para seis par&amp;aacute;metros la definici&amp;oacute;n del gen&amp;eacute;rico ser&amp;iacute;a algo as&amp;iacute; como:
&lt;pre&gt;&lt;code&gt;  public delegate &lt;br /&gt;         TResult Func&amp;lt;T1, T2, T3, T4, T5, T6, TResult&amp;gt;&lt;br /&gt;                 (T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6);&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;Pero ahora aparece un peque&amp;ntilde;o problema: las funciones sin retorno no pueden referenciarse con delegados de tipo &lt;code&gt;Func&lt;/code&gt;, puesto que el framework .NET no soporta la instanciaci&amp;oacute;n de tipos gen&amp;eacute;ricos utilizando par&amp;aacute;metros &lt;code&gt;void&lt;/code&gt; (&lt;a hreflang="en" href="http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-335.pdf" title="Common Language Infrastructure (CLI)"&gt;ECMA 335&lt;/a&gt;, secci&amp;oacute;n 9.4, p&amp;aacute;g. 153). Por tanto, no podr&amp;iacute;amos declarar un delegado como &lt;code&gt;Func&amp;lt;int, void&amp;gt;&lt;/code&gt; para apuntar hacia una funci&amp;oacute;n que recibe un entero y no devuelve nada. Si lo pens&amp;aacute;is un poco, este es el motivo de que no exista ninguna sobrecarga de la clase &lt;code&gt;Func&lt;/code&gt; sin par&amp;aacute;metros gen&amp;eacute;ricos, pues como m&amp;iacute;nimo debemos indicar el tipo del valor de retorno.&lt;br /&gt;&lt;br /&gt;La clave para cubrir estos casos se encuentra en el tipo &lt;code&gt;Action&lt;/code&gt;. Como comentaba unas l&amp;iacute;neas m&amp;aacute;s arriba, el objeto de estos tipos de delegados es apuntar a expresiones lambda que realicen acciones y que no retornen ning&amp;uacute;n valor, por lo que sus par&amp;aacute;metros gen&amp;eacute;ricos describir&amp;aacute;n exclusivamente los tipos de los par&amp;aacute;metros de la funci&amp;oacute;n. En este caso, como es obvio, s&amp;iacute; existe una clase no parametrizada &lt;code&gt;Action&lt;/code&gt; para apuntar a funciones sin par&amp;aacute;metros, adem&amp;aacute;s de disponer de gen&amp;eacute;ricos que cubren las acciones de hasta cuatro par&amp;aacute;metros. Veamos unos ejemplos:&lt;br /&gt;
&lt;pre&gt;&lt;code&gt;  &lt;span style="color:green;"&gt;// Acci&amp;oacute;n sin par&amp;aacute;metros (no gen&amp;eacute;rica):&lt;/span&gt;&lt;br /&gt;  Action saluda = () =&amp;gt; Console.WriteLine(&amp;quot;hola&amp;quot;);&lt;br /&gt;  saluda();  &lt;span style="color:green;"&gt;// Muestra &amp;quot;hola&amp;quot;;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:green;"&gt;// Acci&amp;oacute;n que recibe un string&lt;/span&gt;&lt;br /&gt;  Action&amp;lt;string&amp;gt; apaga = motivo =&amp;gt; { &lt;br /&gt;                                      log(motivo);&lt;br /&gt;                                      shutdown();&lt;br /&gt;                                   };&lt;br /&gt;  apaga(&amp;quot;mantenimiento&amp;quot;); &lt;span style="color:green;"&gt;// Apaga el sistema&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;Por &amp;uacute;ltimo, me parece interesante recordar algo que hab&amp;iacute;a comentado en el post anterior, que en las expresiones lambda no era necesario indicar el tipo de los par&amp;aacute;metros ni del retorno porque el compilador los infer&amp;iacute;a del contexto. Como podemos ver, lo tiene bastante f&amp;aacute;cil, puesto que simplemente debe tomar la definici&amp;oacute;n del delegado para conocerlos; por eso no es necesario introducir redundancias como las siguientes:
&lt;pre&gt;&lt;code&gt;  Func&amp;lt;&lt;span style="background-color:#ffc0ff;"&gt;int&lt;/span&gt;, &lt;span style="background-color:#ffffc0;"&gt;int&lt;/span&gt;&amp;gt; duplica = (&lt;span style="background-color:#ffc0ff;"&gt;int&lt;/span&gt; a) =&amp;gt; (&lt;span style="background-color:#ffffc0;"&gt;int&lt;/span&gt;)(a * 2); &lt;span style="color:green;"&gt;// &amp;iexcl;Redundante!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  &lt;span style="color:green;"&gt;// Forma m&amp;aacute;s c&amp;oacute;moda:&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  Func&amp;lt;&lt;span style="background-color:#ffc0ff;"&gt;int&lt;/span&gt;, &lt;span style="background-color:#ffffc0;"&gt;int&lt;/span&gt;&amp;gt; duplica =  a =&amp;gt; a * 2; &lt;span style="color:green;"&gt;// Ok!&lt;/span&gt;&lt;/code&gt;&lt;span&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;
&lt;p&gt;En cualquier caso, si por alg&amp;uacute;n motivo es necesario utilizar la forma expl&amp;iacute;cita, sabed que no se permite hacerlo de forma parcial, es decir, o le pon&amp;eacute;is los tipos a todo, o no se los pon&amp;eacute;is a nada.&lt;br /&gt;&lt;br /&gt;Y hasta aqu&amp;iacute; esta segunda entrega. En el siguiente post, el &amp;uacute;ltimo de la serie, estudiaremos el uso de las &lt;/p&gt;
&lt;/div&gt;
&lt;/span&gt;&lt;a href="http://www.variablenotfound.com/2009/03/c-desmitificando-las-expresiones-lambda_2829.html"&gt;&lt;span style="color:#35537a;"&gt;lambda como herramientas de definici&amp;oacute;n de &amp;aacute;rboles de expresi&amp;oacute;n&lt;/span&gt;&lt;/a&gt;&lt;span&gt;.&lt;br /&gt;&lt;br /&gt;Por supuesto, para cualquier duda o sugerencia, ya sab&amp;eacute;is d&amp;oacute;nde encontrarme. :-)&lt;br /&gt;&lt;br /&gt;Publicado en: &lt;/span&gt;&lt;a href="http://www.variablenotfound.com"&gt;&lt;span style="color:#35537a;"&gt;www.variablenotfound.com&lt;/span&gt;&lt;/a&gt;&lt;span&gt;.&lt;/span&gt;&lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=147071" 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/vs2008/default.aspx">vs2008</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/linq/default.aspx">linq</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/lambdas/default.aspx">lambdas</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/delegados/default.aspx">delegados</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/m_26002300_233_3B00_todos+an_26002300_243_3B00_nimos/default.aspx">m&amp;#233;todos an&amp;#243;nimos</category></item><item><title>C#: Desmitificando las expresiones lambda (I)</title><link>http://geeks.ms/blogs/jmaguilar/archive/2009/04/12/c-desmitificando-las-expresiones-lambda-i.aspx</link><pubDate>Sun, 12 Apr 2009 21:59:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:146631</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=146631</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2009/04/12/c-desmitificando-las-expresiones-lambda-i.aspx#comments</comments><description>&lt;div class="post-header-line-1"&gt;&lt;/div&gt;
&lt;p class="post-body entry-content"&gt;&lt;img src="http://3.bp.blogspot.com/_O9D62hXq-ng/SQtrgaCIm9I/AAAAAAAAA6k/XuuGqsiLjkw/s200/lambdas.jpg" alt="Lambda" border="0" id="BLOGGER_PHOTO_ID_5263418794000817106" style="float:right;margin:0px 0px 10px 10px;" /&gt;Entre las m&amp;uacute;ltiples novedades aparecidas con C# 3.0 y VB.NET 9.0, las &lt;em&gt;expresiones lambda&lt;/em&gt; son sin duda una de las que en principio pueden parecer m&amp;aacute;s complejas, probablemente por su relaci&amp;oacute;n con conceptos no demasiado asimilables como los delegados, inferencia de tipado, m&amp;eacute;todos an&amp;oacute;nimos, o tipos gen&amp;eacute;ricos, entre otros.&lt;br /&gt;&lt;br /&gt;Sin embargo, esa aparente dificultad desaparece en cuanto se les presta un poco de atenci&amp;oacute;n, y una vez comprendidas aportan a los desarrolladores una potencia y agilidad dif&amp;iacute;ciles de lograr con las herramientas disponibles hasta el momento. S&amp;oacute;lo hay que ver su amplia utilizaci&amp;oacute;n dentro del propio .NET framework, LINQ, y nuevas plataformas como ASP.NET MVC, para darse cuenta de su importancia. Y por si fuera poco, seg&amp;uacute;n cuentan los expertos, &lt;a hreflang="en" href="http://blog.wekeroad.com/blog/my-personal-lambda-crusade/" title="Rob Conery, My Personal Lambda Crusade"&gt;su uso &amp;quot;engancha&amp;quot;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;A lo largo de esta serie de tres posts intentar&amp;eacute; describir las expresiones lambda desde un punto de vista pr&amp;aacute;ctico, con la &amp;uacute;nica pretensi&amp;oacute;n de aportar algo de luz a los que todav&amp;iacute;a no han sucumbido a su poder. ;-)&lt;br /&gt;&lt;br /&gt;El objetivo de este primer post es puramente introductorio, y tratar&amp;eacute; conceptos y nociones b&amp;aacute;sicas para poder abordar los siguientes. En el segundo post de la serie trataremos las expresiones lambda como funciones an&amp;oacute;nimas, dejando para el tercero los &lt;em&gt;misteriosos&lt;/em&gt; &amp;aacute;rboles de expresi&amp;oacute;n.&lt;/p&gt;
&lt;h3 class="post-body entry-content" id="intro"&gt;Introducci&amp;oacute;n a las lambda&lt;/h3&gt;
&lt;div class="post-body entry-content"&gt;Seg&amp;uacute;n la definici&amp;oacute;n en la &lt;a href="http://msdn.microsoft.com/es-es/library/bb397687.aspx" title="Expresiones lambda, Referencia del lenguaje C#"&gt;&lt;span style="color:#35537a;"&gt;Referencia del lenguaje C# de MSDN&lt;/span&gt;&lt;/a&gt;:&lt;br /&gt;&lt;/div&gt;
&lt;blockquote class="post-body entry-content"&gt;&amp;quot;Una expresi&amp;oacute;n lambda es una funci&amp;oacute;n an&amp;oacute;nima que puede contener expresiones e instrucciones y se puede utilizar para crear delegados o tipos de &amp;aacute;rboles de expresi&amp;oacute;n&amp;quot;&lt;/blockquote&gt;
&lt;div class="post-body entry-content"&gt;En la &lt;a href="http://msdn.microsoft.com/es-es/library/bb531253.aspx" title="Expresiones lambda, en la Gu&amp;iacute;a de Programaci&amp;oacute;n de Visual Basic"&gt;&lt;span style="color:#35537a;"&gt;Gu&amp;iacute;a de programaci&amp;oacute;n de Visual Basic 9&lt;/span&gt;&lt;/a&gt; encontramos otra definici&amp;oacute;n, muy simple y pragm&amp;aacute;tica: &lt;/div&gt;
&lt;blockquote class="post-body entry-content"&gt;&amp;quot;Una expresi&amp;oacute;n lambda es una funci&amp;oacute;n sin nombre que calcula y devuelve un solo valor. Se pueden utilizar las expresiones lambda dondequiera que un tipo de delegado sea v&amp;aacute;lido&amp;quot;&lt;/blockquote&gt;
&lt;div class="post-body entry-content"&gt;&lt;a hreflang="en" href="http://weblogs.asp.net/scottgu/archive/2007/04/08/new-orcas-language-feature-lambda-expressions.aspx" title="New &amp;#39;Orcas&amp;#39; Language Feature: Lambda Expressions"&gt;ScottGu&lt;/a&gt; tambi&amp;eacute;n aport&amp;oacute; su granito de arena para hacer el concepto m&amp;aacute;s cercano a los desarrolladores; como siempre, al grano: &lt;/div&gt;
&lt;blockquote class="post-body entry-content"&gt;&amp;quot;Las Expresiones Lambda aportan una sintaxis m&amp;aacute;s concisa y funcional para escribir m&amp;eacute;todos an&amp;oacute;nimos.&amp;quot;&lt;br /&gt;[...]&lt;br /&gt;&amp;quot;La forma m&amp;aacute;s sencilla para conceptualizar las expresiones lambda es pensar en ellas como formas de escribir m&amp;eacute;todos breves en una l&amp;iacute;nea.&amp;quot;&lt;/blockquote&gt;
&lt;div class="post-body entry-content"&gt;Partiendo de estas definiciones, y de otras muchas aportadas por Google ;-), est&amp;aacute; claro que las lambda son funciones, es decir, un conjunto de intrucciones capaces de retornar un valor partiendo de los par&amp;aacute;metros que se les suministra, aunque en determinados casos es posible que no reciba ning&amp;uacute;n par&amp;aacute;metro, o que realicen una acci&amp;oacute;n sin retornar nada. Igual que una funci&amp;oacute;n tradicional, vaya. Y de hecho, en el cuerpo de una expresi&amp;oacute;n lambda puede haber &lt;em&gt;casi&lt;/em&gt; de todo: llamadas a otras funciones, expresiones, bucles, declaraciones de variables...&lt;br /&gt;&lt;br /&gt;Sin embargo, a diferencia de los m&amp;eacute;todos o funciones habituales, las lambdas no necesitan de un identificador, puesto que se declaran in situ, justo en el momento en que van a asignarse a una variable o a utilizarse como par&amp;aacute;metro de una funci&amp;oacute;n, pasando el destinatario de esta asignaci&amp;oacute;n a actuar como delegado, o puntero, hacia la misma, o a ser el contenedor del &amp;aacute;rbol de expresi&amp;oacute;n que la representa. Ein? Chino, eh? No pasa nada, dentro de poco estudiaremos estos dos usos en profundidad, pero antes vamos a ver c&amp;oacute;mo se definen las expresiones lambda a nivel de c&amp;oacute;digo.&lt;br /&gt;&lt;/div&gt;
&lt;h3 class="post-body entry-content" id="forma"&gt;Forma de las expresiones lambda&lt;/h3&gt;
&lt;div class="post-body entry-content"&gt;Las expresiones lambda en C# se escriben seg&amp;uacute;n el patr&amp;oacute;n descrito a continuaci&amp;oacute;n, al que le siguen algunos ejemplos que lo ilustran e introducen algunas particularidades. &lt;/div&gt;
&lt;div class="post-body entry-content"&gt;
&lt;pre&gt;&lt;code&gt;&lt;div style="background-color:#ffffc0;border:#c0c0c0 1px dotted;padding:3px;"&gt;Forma general: &lt;strong&gt;par&amp;aacute;metros =&amp;gt; expresi&amp;oacute;n&lt;/strong&gt;, donde:&lt;br /&gt;- &lt;strong&gt;par&amp;aacute;metros&lt;/strong&gt;: lista de par&amp;aacute;metros separados por comas&lt;br /&gt;- &lt;strong&gt;&amp;quot;=&amp;gt;&amp;quot;&lt;/strong&gt; : separador.&lt;br /&gt;- &lt;strong&gt;expresi&amp;oacute;n&lt;/strong&gt;: implementaci&amp;oacute;n de las operaciones a realizar&lt;/div&gt;&lt;br /&gt;num =&amp;gt; num * 2     &lt;span style="color:green;"&gt;// Lambda con un par&amp;aacute;metro que retorna&lt;br /&gt;                   // el doble del valor que se le pasa.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;(a, b) =&amp;gt; a + b    &lt;span style="color:green;"&gt;// Lambda con dos par&amp;aacute;metros que retorna&lt;br /&gt;                   // la suma de ambos.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;num =&amp;gt; {                        &lt;span style="color:green;"&gt;// Lambda con cuerpo que recibe un &lt;/span&gt;&lt;br /&gt;   int x = new Random().Next(); &lt;span style="color:green;"&gt;// entero, y retorna la suma de &amp;eacute;ste&lt;/span&gt;&lt;br /&gt;   return num+x;                &lt;span style="color:green;"&gt;// con un n&amp;uacute;mero aleatorio.&lt;/span&gt;&lt;br /&gt;}  &lt;br /&gt;&lt;br /&gt;() =&amp;gt; DateTime.Now &lt;span style="color:green;"&gt;// Lambda que no recibe par&amp;aacute;metros&lt;br /&gt;                   // y retorna la fecha y hora del sistema.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;msg =&amp;gt; Console.WriteLine(msg); &lt;span style="color:green;"&gt;// Recibe un par&amp;aacute;metro, realiza una&lt;br /&gt;                               // acci&amp;oacute;n y no retorna nada.&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="post-body entry-content"&gt;&amp;nbsp;&lt;br /&gt;Como se puede observar, cuando s&amp;oacute;lo existe un par&amp;aacute;metro no es necesario utilizar par&amp;eacute;ntesis en el lado izquierdo de la expresi&amp;oacute;n, mientras que hay que hacerlo en todos los dem&amp;aacute;s casos. Tambi&amp;eacute;n es interesante destacar que las lambda con cuerpo deben utilizar &lt;code&gt;return&lt;/code&gt; para retornar el valor deseado, cuando esto sea necesario.&lt;br /&gt;&lt;br /&gt;Y un &amp;uacute;ltimo dato: fijaos que ni los par&amp;aacute;metros ni el retorno de la funci&amp;oacute;n tienen indicado un tipo. Aunque puede hacerse, normalmente no ser&amp;aacute; necesario puesto que el compilador podr&amp;aacute; inferir (deducir) el tipo a partir de su contexto, m&amp;aacute;s adelante veremos c&amp;oacute;mo es esto posible. Por tanto, &lt;strong&gt;no&lt;/strong&gt; es necesario escribir c&amp;oacute;digo tan extenso como: &lt;/div&gt;
&lt;div class="post-body entry-content"&gt;
&lt;pre&gt;&lt;code&gt;  (int a, int b) =&amp;gt; (int)(a+b)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;div class="post-body entry-content"&gt;&amp;nbsp;&lt;br /&gt;Y hasta aqu&amp;iacute; este primer post introductorio. En el siguiente trataremos de explicar el papel de &lt;a href="http://www.variablenotfound.com/2009/03/c-desmitificando-las-expresiones-lambda_29.html"&gt;&lt;span style="color:#35537a;"&gt;las expresiones lambda como funciones an&amp;oacute;nimas y facilitadoras del trabajo con delegados&lt;/span&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Continuar leyendo la siguiente entrega: &lt;a href="http://www.variablenotfound.com/2009/03/c-desmitificando-las-expresiones-lambda_29.html" title="Desmitificando las expresiones lambda, toma 2."&gt;C#: Desmitificando las expresiones lambda (II)&lt;/a&gt;&lt;/div&gt;
&lt;div class="post-body entry-content"&gt;&lt;/div&gt;
&lt;div class="post-body entry-content"&gt;Publicado en: &lt;a href="http://www.variablenotfound.com/"&gt;&lt;span style="color:#35537a;"&gt;www.variablenotfound.com&lt;/span&gt;&lt;/a&gt;. &lt;/div&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;&lt;img src="http://geeks.ms/aggbug.aspx?PostID=146631" 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/vs2008/default.aspx">vs2008</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/linq/default.aspx">linq</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/_26002300_225_3B00_rboles+de+expresi_26002300_243_3B00_n/default.aspx">&amp;#225;rboles de expresi&amp;#243;n</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/lambdas/default.aspx">lambdas</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/delegados/default.aspx">delegados</category></item><item><title>Inclusión de elementos en el encabezado de una página de contenidos ASP.NET</title><link>http://geeks.ms/blogs/jmaguilar/archive/2009/01/27/inclusi-243-n-de-elementos-en-el-encabezado-de-una-p-225-gina-de-contenidos-asp-net.aspx</link><pubDate>Tue, 27 Jan 2009 22:50:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:140613</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=140613</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2009/01/27/inclusi-243-n-de-elementos-en-el-encabezado-de-una-p-225-gina-de-contenidos-asp-net.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://2.bp.blogspot.com/_O9D62hXq-ng/SV-skwHNdiI/AAAAAAAAA-U/uE7UD_hOsu0/s1600-h/VisualStudio.gif"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/_O9D62hXq-ng/SV-skwHNdiI/AAAAAAAAA-U/uE7UD_hOsu0/s400/VisualStudio.gif" alt="Logo de Visual Studio" style="float:right;margin:0px 0px 10px 10px;" id="BLOGGER_PHOTO_ID_5287134234946663970" /&gt;&lt;/a&gt;Un detalle que llama la atenci&amp;oacute;n al a&amp;ntilde;adir una p&amp;aacute;gina maestra a un proyecto ASP.NET desde Visual Studio 2008 es que, por defecto, a&amp;ntilde;ade dos secciones de contenido (&lt;code&gt;ContentPlaceHolder&lt;/code&gt;) a la estructura de la p&amp;aacute;gina. &lt;br /&gt;&lt;br /&gt;Una de ellas es la habitual, en el cuerpo de &lt;code&gt;&amp;lt;form runat=&amp;quot;server&amp;quot;&amp;gt;&lt;/code&gt;, que es donde las p&amp;aacute;ginas basadas en esa &lt;code&gt;MasterPage&lt;/code&gt; introducir&amp;aacute;n sus contenidos y controles. La otra, sin embargo, es una novedad respecto a versiones anteriores del IDE: en la secci&amp;oacute;n &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; del documento:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;head runat=&amp;quot;server&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;title&amp;gt;&amp;lt;/title&amp;gt;&lt;br /&gt;&lt;span style="background-color:#f0f090;"&gt;    &amp;lt;asp:ContentPlaceHolder ID=&amp;quot;head&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;/asp:ContentPlaceHolder&amp;gt;&lt;/span&gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;&amp;lt;body&amp;gt;&lt;br /&gt;    &amp;lt;form id=&amp;quot;form1&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt;&lt;br /&gt;    &amp;lt;div&amp;gt;&lt;br /&gt;        &amp;lt;asp:ContentPlaceHolder ID=&amp;quot;ContentPlaceHolder1&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt;&lt;br /&gt;        &amp;lt;/asp:ContentPlaceHolder&amp;gt;&lt;br /&gt;    &amp;lt;/div&amp;gt;&lt;br /&gt;    &amp;lt;/form&amp;gt;&lt;br /&gt;&amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;br /&gt;Como habr&amp;eacute;is deducido, esto nos permite introducir contenidos personalizados en la secci&amp;oacute;n &lt;code&gt;&amp;lt;head&amp;gt;&lt;/code&gt; de &lt;strong&gt;una p&amp;aacute;gina concreto&lt;/strong&gt;, como &lt;em&gt;meta tags&lt;/em&gt;, o referencias a scripts que deseamos que se carguen con la p&amp;aacute;gina, evitando tener que incluirlos mediante programaci&amp;oacute;n. As&amp;iacute;, si por ejemplo deseamos introducir una referencia a la librer&amp;iacute;a jQuery en una p&amp;aacute;gina, la implementaci&amp;oacute;n de &amp;eacute;sta incluir&amp;iacute;a los dos &lt;em&gt;placeholders&lt;/em&gt;, tal y como sigue:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;&amp;lt;asp:Content ID=&amp;quot;Content1&amp;quot; ContentPlaceHolderID=&amp;quot;head&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt;&lt;br /&gt;   &amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;/scripts/jquery.js&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;/asp:Content&amp;gt;&lt;br /&gt;&lt;br /&gt;&amp;lt;asp:Content ID=&amp;quot;Content2&amp;quot; ContentPlaceHolderID=&amp;quot;ContentPlaceHolder1&amp;quot; runat=&amp;quot;server&amp;quot;&amp;gt;&lt;br /&gt;   &amp;lt;!-- contenidos del webform --&amp;gt;&lt;br /&gt;&amp;lt;/asp:Content&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&amp;nbsp;&lt;br /&gt;La buena noticia para los que todav&amp;iacute;a trabajamos con Visual Studio 2005 es que podemos aplicar esta misma t&amp;eacute;cnica desde esta versi&amp;oacute;n. Aunque por defecto el IDE no incluye el &lt;code&gt;ContentPlaceHolder&lt;/code&gt; en el encabezado, podemos a&amp;ntilde;adirlo a mano para que quede como en el c&amp;oacute;digo mostrado anteriormente, y el efecto ser&amp;aacute; id&amp;eacute;ntico. &lt;br /&gt;&lt;br /&gt;Eso s&amp;iacute;, a cambio tendremos que aguantar que el entorno nos avise de que la etiqueta no es correcta en ese punto, puesto que s&amp;oacute;lo VS2008 es capaz de interpretarlo correctamente, pero se trata s&amp;oacute;lo de un molesto aviso, que no influir&amp;aacute; en la compilaci&amp;oacute;n o ejecuci&amp;oacute;n de las p&amp;aacute;ginas.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Publicado en: &lt;a href="http://www.variablenotfound.com/"&gt;&lt;span style="color:#35537a;"&gt;www.variablenotfound.com&lt;/span&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=140613" 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/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/vs2008/default.aspx">vs2008</category></item><item><title>Microsoft Chart Control para ASP.NET 3.5 SP1 </title><link>http://geeks.ms/blogs/jmaguilar/archive/2008/12/14/microsoft-chart-control-para-asp-net-3-5-sp1.aspx</link><pubDate>Sun, 14 Dec 2008 22:47:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:129295</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=129295</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2008/12/14/microsoft-chart-control-para-asp-net-3-5-sp1.aspx#comments</comments><description>&lt;p&gt;&lt;img id="BLOGGER_PHOTO_ID_5273785013924765858" style="FLOAT:right;MARGIN:0px 0px 10px 10px;" alt="Popurrí de tipos de gráficas permitidas" src="http://1.bp.blogspot.com/_O9D62hXq-ng/STA_h0jDoKI/AAAAAAAAA8k/gBhvakDR6qw/s400/chart-gallery.jpg" border="0" /&gt;Pues tiene una pinta excelente el control para la generación de gráficas estadísticas Chart Control para ASP.NET 3.5, recientemente presentado en sociedad por &lt;a title="New ASP.NET Charting Control: asp:chart runat=&amp;#39;server&amp;#39;" href="http://weblogs.asp.net/scottgu/archive/2008/11/24/new-asp-net-charting-control-lt-asp-chart-runat-quot-server-quot-gt.aspx"&gt;Scottgu&lt;/a&gt; (con la habitual &lt;a title="Nuevo control de ASP.NET: asp:chart runat=&amp;#39;server&amp;#39;" href="http://thinkingindotnet.wordpress.com/2008/11/27/nuevo-control-de-aspnet/"&gt;&lt;font color="#35537a"&gt;traducción en Thinking in .net&lt;/font&gt;&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;Se trata de un componente con una versión específica para ASP.NET, válida para WebForms y MVC framework, y otra para Windows Forms, que permite generar gráficas estadísticas prácticamente de cualquier tipo, visualmente muy atractivas, realmente fáciles de utilizar en nuestas aplicaciones y, además, de forma gratuita.&lt;br /&gt;&lt;br /&gt;Enumero características interesantes, o que me han llamado la atención (ambas cosas no están necesariamente unidas ;-)), del control para ASP.NET: 
&lt;ul&gt;
&lt;li&gt;El control se renderiza en cliente con una etiqueta &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt;. 
&lt;li&gt;Se puede forzar al control a generar las imágenes al vuelo o a almacenarlas físicamente en una carpeta. 
&lt;li&gt;Las imágenes generadas pueden ser cacheadas para mejorar el rendimiento. 
&lt;li&gt;Genera BMPs, JPGs, PNGs o EMFs. 
&lt;li&gt;Permite también usarlo con aplicaciones no ASP.NET 3.5 a través del modo &amp;quot;binary streaming&amp;quot;, que fuerza a que el control elimine toda la salida HTML de la página donde se encuentra y retorne únicamente la imagen como resultado, de forma dicha página puede ser utilizada como &lt;em&gt;source&lt;/em&gt; de un tag &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; en otro sitio. 
&lt;li&gt;Soporta eventos del tipo &amp;quot;PrePaint&amp;quot; y &amp;quot;PostPaint&amp;quot; para poder hacer retoques a mano sobre los resultados, como:&lt;pre&gt;&lt;code&gt;void Chart1_PostPaint(object sender, ChartPaintEventArgs e)&lt;br /&gt;{&lt;br /&gt;  e.ChartGraphics.Graphics.DrawString(&amp;quot;Hola&amp;quot;, &lt;br /&gt;                                      new Font(&amp;quot;Arial&amp;quot;, 12f), &lt;br /&gt;                                      Brushes.Black, 10, 10);&lt;br /&gt;}&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&amp;nbsp;&lt;br /&gt;
&lt;li&gt;25 tipos de gráficas, muchas de ellas con vistas en tres dimensiones, en las que se puede modificar prácticamente todo: rotación, inclinación, sombras, etc. 
&lt;li&gt;Podemos crear imágenes con múltiples gráficas distintas, utilizar en ellas todas las series de datos que deseemos, con un número ilimitado de puntos. 
&lt;li&gt;Control total sobre los ejes en cuanto a escalado, visualización o etiquetado. 
&lt;li&gt;Posibilidad de añadir anotaciones, leyendas y otros elementos &amp;quot;extra&amp;quot;. 
&lt;li&gt;Permite establecer datos enlazando el control a fuentes (binding), o de forma manual sobre el mismo utilizando los diseñadores o etiquetas ASP.NET. 
&lt;li&gt;Soporta mapeo de imágenes, posibilidad de capturar clicks sobre áreas para establecer comportamientos personalizados, o combinarlo con Ajax para enriquecer la experiencia de usuario.&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3&gt;Instalación&lt;/h3&gt;
&lt;p&gt;Antes de instalar, asegúrate que cumples el requisito previo básico, tener instalado &lt;a href="http://www.microsoft.com/downloads/details.aspx?displaylang=es&amp;amp;FamilyID=ab99342f-5d1a-413d-8319-81da479ab0d7"&gt;&lt;font color="#35537a"&gt;Microsoft .NET Framework 3.5 SP1&lt;/font&gt;&lt;/a&gt;. Si no lo has hecho antes, ya sabes por dónde empezar ;-)&lt;br /&gt;&lt;br /&gt;Una vez asegurado este punto, el siguiente paso es descargar &lt;a href="http://www.microsoft.com/downloads/details.aspx?displaylang=es&amp;amp;FamilyID=130f7986-bf49-4fe5-9ca8-910ae6ea442c"&gt;&lt;font color="#35537a"&gt;Microsoft Chart Control&lt;/font&gt;&lt;/a&gt;, que incluye controles tanto para ASP.NET como para Windows Forms. Existe también, como descarga opcional, el &lt;a href="http://www.microsoft.com/downloads/details.aspx?displaylang=es&amp;amp;FamilyID=581ff4e3-749f-4454-a5e3-de4c463143bd"&gt;&lt;font color="#35537a"&gt;paquete de idioma para Microsoft Chart Control&lt;/font&gt;&lt;/a&gt;, que contiene la localización del producto para otros idiomas.&lt;br /&gt;&lt;br /&gt;Después, es una buena idea instalar el &lt;a title="Descargar el Add-on para Visual Studio" href="http://www.microsoft.com/downloads/details.aspx?familyid=1D69CE13-E1E5-4315-825C-F14D33A303E9&amp;amp;displaylang=en"&gt;&lt;font color="#35537a"&gt;Add-on para Visual Studio 2008&lt;/font&gt;&lt;/a&gt; que os facilitará el trabajo con el control desde este entorno de desarrollo, a base de diseñadores integrados. No olvidéis también bajaros también &lt;a title="Documentación de Microsoft Chart Control para ASP.NET 3.5 SP1" href="http://www.microsoft.com/downloads/details.aspx?FamilyId=EE8F6F35-B087-4324-9DBA-6DD5E844FD9F&amp;amp;displaylang=en"&gt;&lt;font color="#35537a"&gt;la documentación&lt;/font&gt;&lt;/a&gt; si váis a necesitar información detallada de las librerías incluidas.&lt;br /&gt;&lt;br /&gt;Y, por último, para tomar conciencia del tipo de resultados que se pueden obtener con este control, el ideal es descargar los &lt;a href="http://code.msdn.microsoft.com/mschart/Release/ProjectReleases.aspx?ReleaseId=1591"&gt;proyectos de demostración&lt;/a&gt;, que os permitirán ver y tocar una auténtica batería de ejemplos seguro muy útiles a la hora de usarlo en vuestros desarrollos, tanto ASP.NET como Winforms.&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5273776257455422818" style="DISPLAY:block;MARGIN:0px auto 10px;TEXT-ALIGN:center;" alt="Prueba del Chart Control" src="http://3.bp.blogspot.com/_O9D62hXq-ng/STA3kIKE_WI/AAAAAAAAA8c/ab2n8G8FbZQ/s400/chart-control-test.jpg" border="0" /&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=129295" width="1" height="1"&gt;</description><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/web/default.aspx">web</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/componentes/default.aspx">componentes</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vs2008/default.aspx">vs2008</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/productividad/default.aspx">productividad</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>Métodos genéricos en C#</title><link>http://geeks.ms/blogs/jmaguilar/archive/2008/11/25/m-233-todos-gen-233-ricos-en-c.aspx</link><pubDate>Tue, 25 Nov 2008 22:32:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:120413</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=120413</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2008/11/25/m-233-todos-gen-233-ricos-en-c.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://3.bp.blogspot.com/_O9D62hXq-ng/SR8GU_zWN3I/AAAAAAAAA8E/dQp4Yu4NE-Y/s1600-h/lupacodigo.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5268937046840719218" style="FLOAT:right;MARGIN:0px 0px 10px 10px;WIDTH:196px;CURSOR:hand;HEIGHT:144px;" alt="Código fuente" src="http://3.bp.blogspot.com/_O9D62hXq-ng/SR8GU_zWN3I/AAAAAAAAA8E/dQp4Yu4NE-Y/s400/lupacodigo.png" border="0" /&gt;&lt;/a&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="Introducción a generics en C#" 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; 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;  public &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; Maximo(&lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; uno, &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; otro)&lt;br /&gt;  {&lt;br /&gt;    if (uno &amp;gt; otro) return uno;&lt;br /&gt;    return otro;&lt;br /&gt;  }&lt;br /&gt;&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;  public &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; Maximo(&lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; uno, &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; otro) { ... }&lt;br /&gt;  public &lt;span style="COLOR:blue;"&gt;long&lt;/span&gt; Maximo(&lt;span style="COLOR:blue;"&gt;long&lt;/span&gt; uno, &lt;span style="COLOR:blue;"&gt;long&lt;/span&gt; otro) { ... }&lt;br /&gt;  public &lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; Maximo(&lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; uno, &lt;span style="COLOR:blue;"&gt;string&lt;/span&gt; otro) { ... }&lt;br /&gt;  public &lt;span style="COLOR:blue;"&gt;float&lt;/span&gt; Maximo(&lt;span style="COLOR:blue;"&gt;float&lt;/span&gt; uno, &lt;span style="COLOR:blue;"&gt;float&lt;/span&gt; otro) { ... }&lt;br /&gt;  &lt;span style="COLOR:green;"&gt;// 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;  public &lt;span style="COLOR:blue;"&gt;object&lt;/span&gt; Maximo(&lt;span style="COLOR:blue;"&gt;IComparable&lt;/span&gt; uno, &lt;span style="COLOR:blue;"&gt;object&lt;/span&gt; otro)&lt;br /&gt;  {&lt;br /&gt;    if (uno.CompareTo(otro) &amp;gt; 0) return uno;&lt;br /&gt;    return otro;&lt;br /&gt;  }&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;int&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;  public &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt; Maximo&amp;lt;&lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;&amp;gt;(&lt;span style="COLOR:blue;"&gt;T&lt;/span&gt; uno, &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt; otro) where &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;: IComparable&lt;br /&gt;  {&lt;br /&gt;    if (uno.CompareTo(otro) &amp;gt; 0) return uno;&lt;br /&gt;    return otro;&lt;br /&gt;  }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;En el código anterior, podemos distinguir el parámetro genérico &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt; encerrado entre ángulos &amp;quot;&amp;lt;&amp;quot; y &amp;quot;&amp;gt;&amp;quot;, justo después del nombre del método y antes de comenzar a describir los parámetros. Es la forma de indicar que &lt;code&gt;Maximo&lt;/code&gt; es genérico y operará sobre un tipo cualquiera al que llamaremos T; lo de usar esta letra es pura convención, podríamos llamarlo de cualquier forma (por ejemplo &lt;code&gt;MiTipo Maximo&amp;lt;MiTipo&amp;gt;(MiTipo uno, MiTipo otro)&lt;/code&gt;), aunque ceñirse a las convenciones de codificación es normalmente una buena idea.&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;int&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:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  public &lt;span style="COLOR:blue;"&gt;TResult&lt;/span&gt; MiMetodo&amp;lt;&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;&amp;gt;(&lt;span style="COLOR:blue;"&gt;T1&lt;/span&gt; param1, &lt;span style="COLOR:blue;"&gt;T2&lt;/span&gt; param2)&lt;br /&gt;  {&lt;br /&gt;      &lt;span style="COLOR:green;"&gt;// ... cuerpo del método&lt;/span&gt;&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;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;code&gt;Maximo&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  public &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt; Maximo&amp;lt;&lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;&amp;gt;(&lt;span style="COLOR:blue;"&gt;T&lt;/span&gt; uno, &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt; otro) where &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;: IComparable&lt;br /&gt;  {&lt;br /&gt;    if (uno.CompareTo(otro) &amp;gt; 0) return uno;&lt;br /&gt;    return otro;&lt;br /&gt;  }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Vamos a centrarnos ahora en la porción final de la firma del método anterior, donde encontramos el código &lt;code&gt;where &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;: IComparable&lt;/code&gt;. Se trata de una restricción mediante la cual estamos indicando al compilador que el tipo T podrá ser cualquiera, siempre que implementente el interfaz &lt;code&gt;IComparable&lt;/code&gt;, lo que nos permitirá realizar la comparación. &lt;br /&gt;&lt;br /&gt;Existen varios tipos de restricciones que podemos utilizar para limitar los tipos permitidos para nuestros métodos parametrizables: &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;where T: struct&lt;/code&gt;, indica que el argumento debe ser un tipo valor. 
&lt;li&gt;&lt;code&gt;where T: class&lt;/code&gt;, indica que T debe ser un tipo referencia. 
&lt;li&gt;&lt;code&gt;where T: 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;where T: &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;where T: &lt;em&gt;nombredeinterfaz&lt;/em&gt;&lt;/code&gt;, el argumento deberá implementar el interfaz indicado. 
&lt;li&gt;&lt;code&gt;where T1: T2&lt;/code&gt;, indica que el argumento T1 debe ser igual o heredar del tipo, también argumento del método, 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 separarán por comas, como aparece en el siguiente ejemplo:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  public &lt;span style="COLOR:blue;"&gt;TResult&lt;/span&gt; MiMetodo&amp;lt;&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;&amp;gt;(&lt;span style="COLOR:blue;"&gt;T1&lt;/span&gt; param1, &lt;span style="COLOR:blue;"&gt;T2&lt;/span&gt; param2)&lt;br /&gt;    where TResult: IEnumerable&lt;br /&gt;    where T1: new(), IComparable&lt;br /&gt;    where T2: IComparable, ICloneable&lt;br /&gt;    {&lt;br /&gt;        &lt;span style="COLOR:green;"&gt;// ... cuerpo del método&lt;/span&gt;&lt;br /&gt;    }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;En cualquier caso, las restricciones no son obligatorias. De hecho, sólo debemos utilizarlas cuando necesitemos restringir los tipos permitidos como parámetros genéricos, como en el ejemplo del método &lt;code&gt;Maximo&amp;lt;T&amp;gt;&lt;/code&gt;, donde es la única forma que tenemos de asegurarnos que las instancias que nos lleguen en los parámetros puedan ser comparables.&lt;br /&gt;&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;  string mazinger = Maximo&amp;lt;string&amp;gt;(&amp;quot;Mazinger&amp;quot;, &amp;quot;Afrodita&amp;quot;);  &lt;br /&gt;  int i99 = Maximo&amp;lt;int&amp;gt;(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;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  string mazinger = Maximo(&amp;quot;Mazinger&amp;quot;, &amp;quot;Afrodita&amp;quot;);  &lt;br /&gt;  int i99 = 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 equivalente a &lt;code&gt;string Maximo(string, string)&lt;/code&gt;, que coincide con la definición del genérico.&lt;br /&gt;&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&amp;lt;T&amp;gt;&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;  public List&amp;lt;&lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;&amp;gt; CreaLista&amp;lt;&lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;&amp;gt;(params &lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;[] pars)&lt;br /&gt;  {&lt;br /&gt;    List&amp;lt;&lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;&amp;gt; list = new List&amp;lt;&lt;span style="COLOR:blue;"&gt;T&lt;/span&gt;&amp;gt;();&lt;br /&gt;    foreach (&lt;span style="COLOR:blue;"&gt;T&lt;/span&gt; elem in pars)&lt;br /&gt;    {&lt;br /&gt;      list.Add(elem);&lt;br /&gt;    }&lt;br /&gt;    return list;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  &lt;span style="COLOR:green;"&gt;// ...&lt;br /&gt;  // Uso:&lt;/span&gt;&lt;br /&gt;  List&amp;lt;&lt;span style="COLOR:blue;"&gt;int&lt;/span&gt;&amp;gt; nums = CreaLista&amp;lt;&lt;span style="COLOR:blue;"&gt;int&lt;/span&gt;&amp;gt;(1, 2, 3, 4, 6, 7);&lt;br /&gt;  List&amp;lt;&lt;span style="COLOR:blue;"&gt;string&lt;/span&gt;&amp;gt; noms = CreaLista&amp;lt;&lt;span style="COLOR:blue;"&gt;string&lt;/span&gt;&amp;gt;(&amp;quot;Pepe&amp;quot;, &amp;quot;Juan&amp;quot;, &amp;quot;Luis&amp;quot;); &lt;br /&gt;&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;  List&amp;lt;&lt;span style="COLOR:blue;"&gt;int&lt;/span&gt;&amp;gt; nums = CreaLista(1, 2, 3, 4, 6, 7);&lt;br /&gt;  List&amp;lt;&lt;span style="COLOR:blue;"&gt;string&lt;/span&gt;&amp;gt; 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;// Incluso con tipos anónimos de C# 3.0:&lt;/span&gt;&lt;br /&gt;  var p = CreaLista(&lt;br /&gt;            new { X = 1, Y = 2 }, &lt;br /&gt;            new { X = 3, Y = 4 }&lt;br /&gt;          );&lt;br /&gt;  Console.WriteLine(p[1].Y); &lt;span style="COLOR:green;"&gt;// Pinta &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 ampliamiente 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=120413" 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></item><item><title>Cómo convertir clases en diccionarios clave/valor</title><link>http://geeks.ms/blogs/jmaguilar/archive/2008/11/16/c-243-mo-convertir-clases-en-diccionarios-clave-valor.aspx</link><pubDate>Sun, 16 Nov 2008 22:40:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:115961</guid><dc:creator>José M. Aguilar</dc:creator><slash:comments>7</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://geeks.ms/blogs/jmaguilar/rsscomments.aspx?PostID=115961</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2008/11/16/c-243-mo-convertir-clases-en-diccionarios-clave-valor.aspx#comments</comments><description>&lt;p&gt;&lt;img id="BLOGGER_PHOTO_ID_5187550580645795922" style="FLOAT:right;MARGIN:0px 0px 10px 10px;" alt="Cuestiones enviadas por lectores" src="http://bp2.blogger.com/_O9D62hXq-ng/R_3hxK3DmFI/AAAAAAAAAVI/lecw8lWubVE/s320/pregunta.png" border="0" /&gt;El otro día, a raíz del post &lt;a href="http://www.variablenotfound.com/2008/10/atajo-para-instanciar-tipos-annimos-en.html"&gt;&lt;font color="#35537a"&gt;Atajo para instanciar tipos anónimos en C# y VB.NET&lt;/font&gt;&lt;/a&gt;, el amigo Leo H., desde Argentina, me envió una cuestión:&lt;br /&gt;
&lt;blockquote&gt;&lt;br /&gt;[...] Me parece muy interesante crear diccionarios utilizando tipos anónimos, pues simplifica de una forma considerable la cantidad de código que hay que escribir para conseguir llenar una estructura de este tipo. De hecho, estoy pensando en utilizar esta técnica en una librería que estoy desarrollando, pero no veo claro cómo transformar después ese objeto anónimo en el diccionario equivalente [...]&lt;br /&gt;&lt;/blockquote&gt;
&lt;p&gt;&lt;br /&gt;Verás que la idea es muy simple. Sólo necesitamos encontrar una fórmula que nos permita recorrer las propiedades del objeto, y por cada una de ellas, añadir la entrada correspondiente en el diccionario, especificando como clave el nombre de la propiedad y como valor el que tenga establecido la misma.&lt;br /&gt;&lt;br /&gt;Una posibilidad muy sencilla es usar la clase &lt;code&gt;TypeDescriptor&lt;/code&gt;, cuyo método &lt;code&gt;GetProperties()&lt;/code&gt; nos devuelve una colección con los descriptores de las propiedades de la instancia que le pasemos como parámetro. Iterando sobre este conjunto, podremos ir llenando el diccionario con los elementos que nos interese, tal que así, dado un objeto llamado &lt;code&gt;obj&lt;/code&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  Dictionary&amp;lt;string, object&amp;gt; dicc = new Dictionary&amp;lt;string, object&amp;gt;();&lt;br /&gt;  foreach (PropertyDescriptor desc in TypeDescriptor.GetProperties(obj))&lt;br /&gt;  {&lt;br /&gt;    dicc.Add(desc.Name, desc.GetValue(obj));&lt;br /&gt;  }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Pero vamos a dar una vuelta de tuerca más. Partiendo del código anterior, es muy fácil crear un &lt;a title="Métodos de extensión en C#" href="http://www.variablenotfound.com/2008/02/mtodos-de-extensin-en-c.html"&gt;&lt;font color="#35537a"&gt;método de extensión&lt;/font&gt;&lt;/a&gt; sobre la clase &lt;code&gt;object&lt;/code&gt;, de forma que podamos convertir en un diccionario cualquier objeto de nuestras aplicaciones, con toda la potencia y comodidad que nos aporta esta técnica.&lt;br /&gt;&lt;br /&gt;El código sería:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  public static class Extensions&lt;br /&gt;  {&lt;br /&gt;    public static Dictionary&amp;lt;string, object&amp;gt; ToDictionary(this object obj)&lt;br /&gt;    {&lt;br /&gt;      Dictionary&amp;lt;string, object&amp;gt; dicc = new Dictionary&amp;lt;string, object&amp;gt;();&lt;br /&gt;      foreach (PropertyDescriptor desc in TypeDescriptor.GetProperties(obj))&lt;br /&gt;      {&lt;br /&gt;        dicc.Add(desc.Name, desc.GetValue(obj));&lt;br /&gt;      }&lt;br /&gt;      return dicc;&lt;br /&gt;    }&lt;br /&gt;  }&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;De esta forma, dispondremos de una potente forma de &amp;quot;diccionarizar&amp;quot; nuestras instancias, sean del tipo que sean, por ejemplo:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt;  var juan = new { nombre = &amp;quot;Juan&amp;quot;, edad = 23 };&lt;br /&gt;  Dictionary&amp;lt;string, object&amp;gt; dicc = juan.ToDictionary();  &lt;br /&gt;  Console.WriteLine(dicc[&amp;quot;nombre&amp;quot;]); // &lt;span style="COLOR:green;"&gt;Escribe &amp;quot;Juan&amp;quot;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;  var dicc2 = &amp;quot;hola&amp;quot;.ToDictionary();&lt;br /&gt;  Console.WriteLine(dicc2[&amp;quot;Length&amp;quot;]);  &lt;span style="COLOR:green;"&gt;// Escribe 4&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Espero que te sea de ayuda, Leo. ¡Y gracias por participar en Variable Not Found!&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=115961" 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/vs2008/default.aspx">vs2008</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/consultas/default.aspx">consultas</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/aspnetmvc/default.aspx">aspnetmvc</category></item><item><title>Intellisense completo para jQuery en Visual Studio 2008</title><link>http://geeks.ms/blogs/jmaguilar/archive/2008/11/09/intellisense-completo-para-jquery-en-visual-studio-2008.aspx</link><pubDate>Sun, 09 Nov 2008 21:59:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:112584</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=112584</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2008/11/09/intellisense-completo-para-jquery-en-visual-studio-2008.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://jquery.com/"&gt;&lt;img id="BLOGGER_PHOTO_ID_5266604258531952882" style="FLOAT:right;MARGIN:0px 0px 10px 10px;WIDTH:200px;CURSOR:hand;HEIGHT:78px;" alt="Visitar jQuery" src="http://3.bp.blogspot.com/_O9D62hXq-ng/SRa8q2JbSPI/AAAAAAAAA70/hezTspVKaNM/s400/jQuery.jpg" border="0" /&gt;&lt;/a&gt;Semanas atrás, Microsoft adelantaba en el &lt;a title="jQuery, Microsoft y tú" href="http://www.variablenotfound.com/2008/09/jquery-microsoft-y-t.html"&gt;&lt;font color="#35537a"&gt;anuncio de la inclusión de jQuery&lt;/font&gt;&lt;/a&gt; en la plataforma de desarrollo de la compañía, que pronto dispondríamos de soporte total de intellisense para jQuery, y ya podemos ver el resultado.&lt;br /&gt;&lt;br /&gt;Por una parte, a finales del pasado mes de octubre se publicó en el sitio de &lt;a title="jQuery downloads" href="http://code.google.com/p/jqueryjs/downloads/list"&gt;descargas de jQuery&lt;/a&gt;, y apareció enlazado desde su propia web oficial, el archivo de anotaciones que permite el disfrute de la experiencia intellisense en todo su esplendor mientras utilizamos la librería desde Visual Studio 2008: información completa sobre los métodos que estamos usando, parámetros, valores de retorno, y autocompletado de escritura. Una gozada, vaya.&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5266607637474528306" style="FLOAT:right;MARGIN:0px 0px 10px 10px;" alt="Explorador de soluciones" src="http://2.bp.blogspot.com/_O9D62hXq-ng/SRa_vhsHTDI/AAAAAAAAA78/Bti5CpvInlI/s400/jquery-vsdoc.jpg" border="0" /&gt;Y aunque pueda parecer lo contrario por su extensión (se trata de un archivo .js), es sólo eso, un archivo de documentación, no una sustitución para la librería original. De hecho, si queremos utilizar jQuery en nuestros proyectos y disfrutar del intellisense, deberemos incluir tanto el archivo original de la librería (en este momento &lt;a title="Download jQuery" href="http://docs.jquery.com/Downloading_jQuery"&gt;&lt;font color="#35537a"&gt;versión 1.2.6&lt;/font&gt;&lt;/a&gt;) como el de anotaciones, denominado denominado &lt;a title="Descargar el archivo" href="http://code.jquery.com/jquery-1.2.6-vsdoc.js"&gt;&lt;font color="#35537a"&gt;jquery-1.2.6-vsdoc.js&lt;/font&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Por otra parte, sólo unos días después, Microsoft ha publicado el &lt;a title="Descargar hotfix para Visual Studio 2008 SP1" href="http://code.msdn.microsoft.com/KB958502/Release/ProjectReleases.aspx?ReleaseId=1736"&gt;&lt;font color="#35537a"&gt;hotfix KB958502&lt;/font&gt;&lt;/a&gt; para Visual Studio 2008 Service Pack 1 (y válido también para Visual Web Developer Express SP1) que hace que el entorno sea capaz de buscar automáticamente los archivos de documentación relativos a cada librería javascript que estemos utilizando, y tomar de ellos la información para activar intellisense. De hecho, por cada archivo javascript referenciado desde nuestro código con un nombre &amp;quot;xxx.js&amp;quot;, el entorno buscará la documentación en el archivo &amp;quot;xxx-vsdocs.js&amp;quot;; si no la encuentra, probará con &amp;quot;xxx.debug.js&amp;quot;, y si tampoco hay nada, dentro de la propia librería &amp;quot;xxx.js&amp;quot;.&lt;br /&gt;&lt;br /&gt;Por tanto, una vez instalado este parche, &lt;strong&gt;si estás utilizando jQuery directamente sobre una página .ASPX&lt;/strong&gt;, algo muy habitual, basta con descargar el archivo de anotaciones e incluirlo en el directorio de scripts del proyecto para que la magia intellisense comience a funcionar en todas las páginas en las que exista una referencia hacia jQuery (un tag &lt;code&gt;&amp;lt;script src=&amp;quot;...&amp;quot;&amp;gt;&lt;/code&gt;), o que se basen en una página maestra que incluya dicha referencia.&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5265629813243312834" style="DISPLAY:block;MARGIN:0px auto 10px;" alt="jQuery + Intellisense!" src="http://2.bp.blogspot.com/_O9D62hXq-ng/SRNGaqkS-sI/AAAAAAAAA7s/PPNk18jdblg/s400/intellisense-jquery-after.jpg" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;strong&gt;Si estás editando un fichero javascript (.js)&lt;/strong&gt; en Visual Studio y desde él quieres utilizar jQuery con intellisense, puedes utilizar un comentario con la etiqueta &lt;code&gt;Reference&lt;/code&gt;, que indica al entorno que puede tomar la documentación de los archivos indicados en la misma. Basta con encabezar el archivo .js así:&lt;/p&gt;&lt;pre&gt;&lt;code&gt;  &lt;span style="COLOR:green;"&gt;/// &amp;lt;reference path=&amp;quot;jquery-1.2.6-vsdoc.js&amp;quot;&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;El comentario, obviamente, no afecta a la ejecución, y sólo es interpretado por el IDE para buscar referencias a archivos de documentación. &lt;br /&gt;&lt;br /&gt;Por último, &lt;a title="VS2008 SP1 Hotfix to Support &amp;#39;-vsdoc.js&amp;#39; IntelliSense Doc Files" href="http://blogs.msdn.com/webdevtools/archive/2008/11/07/hotfix-to-enable-vsdoc-js-intellisense-doc-files-is-now-available.aspx"&gt;como apunta Jeff King&lt;/a&gt;, Program Manager en el equipo de herramientas para la Web de Visual Studio, es conveniente aclarar que el objetivo de este parche no es únicamente dar soporte a jQuery; se trata de una solución general para facilitar la integración de documentación de librerías javascript en el entorno de desarrollo, y que seguro vamos a poder aprovechar en muchas otras ocasiones.&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=112584" width="1" height="1"&gt;</description><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/vs2008/default.aspx">vs2008</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/jquery/default.aspx">jquery</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>Plantillas de proyectos de tests NUnit para ASP.NET MVC Preview 3</title><link>http://geeks.ms/blogs/jmaguilar/archive/2008/06/30/plantillas-de-proyectos-de-tests-nunit-para-asp-net-mvc-preview-3.aspx</link><pubDate>Mon, 30 Jun 2008 19:56:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:90300</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=90300</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2008/06/30/plantillas-de-proyectos-de-tests-nunit-para-asp-net-mvc-preview-3.aspx#comments</comments><description>&lt;p&gt;&lt;img id="BLOGGER_PHOTO_ID_5215188949054000450" style="FLOAT:right;MARGIN:0px 0px 10px 10px;" alt="NUnit" src="http://bp1.blogger.com/_O9D62hXq-ng/SGASt8joDUI/AAAAAAAAAjU/q4hSaS20324/s200/nunit.gif" border="0" /&gt;La inclusión en el SP1 (Beta) de Visual Web Developer Express 2008 de soporte para librerías de clases y aplicaciones Web, abriendo el uso del framework MVC Preview 3 para los que estamos aprendiendo con esta herramienta, era sin duda una novedad sorprendente, pero no la única. &lt;br /&gt;&lt;br /&gt;Joe Cartano comentaba hace unas semanas, en el &lt;a title="[ING] ASP.NET MVC Preview 3 Tooling Updates And Updated NUnit Test Project Templates " href="http://blogs.msdn.com/webdevtools/archive/2008/05/30/asp-net-mvc-preview-3-tooling-updates.aspx"&gt;&lt;font color="#35537a"&gt;blog oficial del equipo de Visual Web Developer&lt;/font&gt;&lt;/a&gt; , las nuevas mejoras de este IDE, y en especial las relativas al soporte para plantillas de terceros, y publicó de paso unas &lt;a title="Descargar plantillas (.zip)" href="http://www.box.net/shared/zmp0cdxsss"&gt;&lt;font color="#35537a"&gt;estupendas plantillas&lt;/font&gt;&lt;/a&gt; para la creación de tests unitarios basados en &lt;a title="[ING] NUnit homepage" href="http://www.nunit.org/"&gt;&lt;font color="#35537a"&gt;NUnit&lt;/font&gt;&lt;/a&gt; en aplicaciones ASP.NET MVC.&lt;br /&gt;&lt;br /&gt;Para instalarlas, basta con descargar el archivo (con el enlace anterior), descomprimirlo sobre un directorio cualquiera y ejecutar el archivo .BAT correspondiente a la versión de Visual Studio que estemos utilizado, siempre con permisos de administrador. Si todo va bien y suponiendo además que tenemos &lt;a title="[ING] Descargar NUnit 2.4.7" href="http://www.nunit.org/index.php?p=download"&gt;&lt;font color="#35537a"&gt;NUnit&lt;/font&gt;&lt;/a&gt; instalado, al crear una nueva aplicación ASP.NET MVC en VWD Express aparecerá un cuadro de diálogo como el siguiente:&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5213310665826593442" style="DISPLAY:block;MARGIN:0px auto 10px;TEXT-ALIGN:center;" alt="Diálogo de creación de un proyecto de tests" src="http://bp1.blogger.com/_O9D62hXq-ng/SFlmbeRZaqI/AAAAAAAAAjE/_f0dIPYBcWo/s400/MVC-nUnit.png" border="0" /&gt;&lt;br /&gt;Esto va en la línea de lo &lt;a title="[ING] ASP.NET MVC Framework (Part 1)" href="http://weblogs.asp.net/scottgu/archive/2007/11/13/asp-net-mvc-framework-part-1.aspx"&gt;&lt;font color="#35537a"&gt;comentado por ScottGu meses atrás&lt;/font&gt;&lt;/a&gt;, en sus primeros posts sobre el nuevo framework MVC, donde aseguraba que se podría utilizar cualquier framework de testing, citando algunos como NUnit y &lt;a title="[ING] Homepage de MBUnit" href="http://www.mbunit.com/"&gt;&lt;font color="#35537a"&gt;MBUnit&lt;/font&gt;&lt;/a&gt;. Y lo de permitir una cierta integración de estos frameworks ajenos a la casa en la versión Express es todo un detalle.&lt;br /&gt;&lt;br /&gt;Si se acepta el diálogo, se creará dentro de la misma solución un proyecto de tipo librería que contendrá las referencias a ensamblados necesarios para su ejecución (NUnit, routing, Mvc, etc.) y con un par de métodos de prueba predefinidos. De esta forma, para comprobar el correcto funcionamiento de nuestras aplicaciones sólo tendremos que ejecutar los tests, aunque de momento, y a diferencia de las versiones superiores de Visual Studio 2008, tendrá que ser desde fuera del entorno, utilizando la consola de NUnit:&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5213315747952956514" style="DISPLAY:block;MARGIN:0px auto 10px;TEXT-ALIGN:center;" alt="WDExpress 2008 y NUnit en ejecución" src="http://bp3.blogger.com/_O9D62hXq-ng/SFlrDSqvlGI/AAAAAAAAAjM/joz2HPMYhtM/s400/nUnitEjecucion.png" border="0" /&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=90300" width="1" height="1"&gt;</description><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vs2008/default.aspx">vs2008</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/aspnetmvc/default.aspx">aspnetmvc</category></item><item><title>ASP.NET MVC Preview 3, por fin para Visual Web Developer Express</title><link>http://geeks.ms/blogs/jmaguilar/archive/2008/06/23/asp-net-mvc-preview-3-por-fin-para-visual-web-developer-express.aspx</link><pubDate>Mon, 23 Jun 2008 21:09:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:89667</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=89667</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2008/06/23/asp-net-mvc-preview-3-por-fin-para-visual-web-developer-express.aspx#comments</comments><description>&lt;p&gt;&lt;img id="BLOGGER_PHOTO_ID_5212576306712340242" style="FLOAT:right;MARGIN:0px 0px 10px 10px;" alt="Visual Studio Logo" src="http://bp0.blogger.com/_O9D62hXq-ng/SFbKiJY05xI/AAAAAAAAAho/_jmcEkGOdoo/s400/VisualStudio.gif" border="0" /&gt;Cuando hace unas semanas &lt;a title="[ING] ASP.NET MVC Preview 3 Release" href="http://weblogs.asp.net/scottgu/archive/2008/05/27/asp-net-mvc-preview-3-release.aspx"&gt;&lt;font color="#35537a"&gt;ScottGu anunció la Preview 3 de ASP.NET MVC&lt;/font&gt;&lt;/a&gt;, quedé muy sorprendido de que al final no viniera con soporte para Visual Web Developer Express 2008, sobre todo teniendo en cuenta que un mes antes &lt;a title="[ING] The Preview 3 will support VWD Express" href="http://weblogs.asp.net/scottgu/archive/2008/04/16/asp-net-mvc-source-refresh-preview.aspx#6107455"&gt;&lt;font color="#35537a"&gt;había adelantado este acontecimiento&lt;/font&gt;&lt;/a&gt; para los que estamos probando la plataforma MVC con esta herramienta.&lt;br /&gt;&lt;br /&gt;Pero no, era una falsa alarma. Scott había olvidado comentarlo, y días más tarde rectificaba en un nuevo post en el que comunicaba que sí &lt;a title="ASP.NET MVC Support with Visual Web Developer 2008 Express " href="http://weblogs.asp.net/scottgu/archive/2008/06/01/asp-net-mvc-support-with-visual-web-developer-2008-express.aspx"&gt;&lt;font color="#35537a"&gt;sería posible usar la Preview 3 desde la versión Express de Web Developer&lt;/font&gt;&lt;/a&gt; sin necesidad de usar &lt;a title="Plantillas de MVC CTP 2 para Web Developer Express" href="http://www.variablenotfound.com/2008/03/probando-aspnet-mvc-preview-2-con-web.html"&gt;&lt;font color="#35537a"&gt;plantillas específicas&lt;/font&gt;&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Desde entonces estaba deseando tener un ratillo para probarlo, y por fin ha llegado el momento.&lt;br /&gt;&lt;br /&gt;En primer lugar, he de aclarar que, aunque pueda parecer lo contrario, no se trata de que el equipo de Microsoft haya introducido cambios en la plataforma MVC para hacerla compatible con la versión Express, sino al revés. Son los nuevos cambios introducidos en el IDE, y principalmente su recién estrenado soporte a proyectos de tipo Aplicación Web, los que hacen posible que funcione directamente sobre esta herramienta.&lt;br /&gt;&lt;br /&gt;Y este es el motivo de que, antes que nada, sea necesario instalar el &lt;a title="[ING] Microsoft Visual Studio 2008 Express Edition with SP1 Beta" href="http://www.microsoft.com/downloads/details.aspx?FamilyId=BDB6391C-05CA-4036-9154-6DF4F6DEBD14&amp;amp;displaylang=en"&gt;&lt;font color="#35537a"&gt;SP1 de .NET Framework 3.5 y de las herramientas Express&lt;/font&gt;&lt;/a&gt; (&lt;strong&gt;aún en Beta&lt;/strong&gt;). Y si váis a hacerlo, mucho ojo, que todas las páginas donde aparece para descargar aparece llena de &lt;em&gt;warnings&lt;/em&gt;; en otras palabras, no recomiendan su instalación en máquinas de verdad, sólo en entornos de prueba. Pero no os preocupéis, que para eso estoy yo ;-)&lt;br /&gt;&lt;br /&gt;Después de un proceso algo lento y un par de reinicios del equipo, el Service Pack 1 Beta queda instalado sin problemas. Sólo falta &lt;a title="[ING] Descarga de ASP.NET MVC Preview 3" href="http://www.microsoft.com/downloads/details.aspx?FamilyId=92F2A8F0-9243-4697-8F9A-FCF6BC9F66AB&amp;amp;displaylang=en"&gt;&lt;font color="#35537a"&gt;descargar y montar la Preview 3 de ASP.NET MVC&lt;/font&gt;&lt;/a&gt; para que al ir a crear un nuevo proyecto desde Visual Web Developer aparezcan la plantilla MVC, entre otras novedades:&lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5212878328787616034" style="DISPLAY:block;MARGIN:0px auto 10px;TEXT-ALIGN:center;" alt="Plantillas disponibles en Web Developer Express 2008 con SP1 Beta" src="http://bp0.blogger.com/_O9D62hXq-ng/SFfdOJS3wSI/AAAAAAAAAhw/tr3pW2xxV08/s400/WDX-MVC.png" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;Y para probar, nada mejor que la &lt;a title="[ING] Updated Northwind Demo For ASP.NET MVC Preview 3" href="http://haacked.com/archive/2008/05/23/updated-northwind-demo.aspx"&gt;&lt;font color="#35537a"&gt;aplicación de demostración sobre Northwind&lt;/font&gt;&lt;/a&gt; que preparó Phil Haack hace unas semanas. Salvo un ligero error de carga debido a que la versión Express no soporta la creación de proyectos de solución (no podremos probar los tests unitarios integrados en VS2008), todo funciona a la perfección. &lt;br /&gt;&lt;br /&gt;&lt;img id="BLOGGER_PHOTO_ID_5212884389516351746" style="DISPLAY:block;MARGIN:0px auto 10px;TEXT-ALIGN:center;" alt="Northwind demo para MVC CTP 3" src="http://bp1.blogger.com/_O9D62hXq-ng/SFfiu7RNGQI/AAAAAAAAAh4/eqpdB5TFOOQ/s400/NorthwindDemoMVC3.png" border="0" /&gt;&lt;br /&gt;&lt;br /&gt;Sí señor. Ahora sí que podemos seguir jugando. :-)&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=89667" 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/asp.net/default.aspx">asp.net</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/web/default.aspx">web</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/vs2008/default.aspx">vs2008</category><category domain="http://geeks.ms/blogs/jmaguilar/archive/tags/aspnetmvc/default.aspx">aspnetmvc</category></item><item><title>Disponible Microsoft Source Analysis for C#</title><link>http://geeks.ms/blogs/jmaguilar/archive/2008/05/24/disponible-el-microsoft-source-analysis-for-c.aspx</link><pubDate>Sat, 24 May 2008 10:51:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:86667</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=86667</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2008/05/24/disponible-el-microsoft-source-analysis-for-c.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://bp3.blogger.com/_O9D62hXq-ng/SDfyEM5OpXI/AAAAAAAAAfY/dnbuRzG00Fo/s1600-h/lupacodigo.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5203894048444556658" style="FLOAT:right;MARGIN:0px 0px 10px 10px;CURSOR:hand;" alt="Análisis de Código" src="http://bp3.blogger.com/_O9D62hXq-ng/SDfyEM5OpXI/AAAAAAAAAfY/dnbuRzG00Fo/s400/lupacodigo.png" border="0" /&gt;&lt;/a&gt;Jason Allor &lt;a title="[ING] Lanzamiento de Microsoft Source Analysis for C#" href="http://blogs.msdn.com/sourceanalysis/archive/2008/05/23/announcing-the-release-of-microsoft-source-analysis.aspx"&gt;&lt;font color="#35537a"&gt;anunciaba ayer mismo&lt;/font&gt;&lt;/a&gt; el lanzamiento de una nueva herramienta, Microsoft Source Analysis for C#, cuyo objetivo es ayudar a los desarrolladores a producir código elegante, legible, mantenible y consistente entre los miembros de un equipo de trabajo. De hecho, era conocida como StyleCop en Microsoft, donde llevan utilizándola ya varios años.&lt;br /&gt;&lt;br /&gt;Y aunque pueda parecer similar a &lt;a title="Variable not found: Mejora la calidad de tus aplicaciones y librerías .Net con FxCop" href="http://www.variablenotfound.com/2008/01/mejora-la-calidad-de-tus-aplicaciones-y.html"&gt;&lt;font color="#35537a"&gt;FxCop&lt;/font&gt;&lt;/a&gt;, Microsoft Source Analysis for C# se centra en el análisis de código fuente y no en ensamblados, lo que hace que pueda afinar mucho más en las reglas de codificación.&lt;br /&gt;&lt;br /&gt;Incluye sobre 200 buenas prácticas, cubriendo aspectos como:&lt;br /&gt;
&lt;ul&gt;
&lt;li&gt;Layout (disposición) de elementos, instrucciones, expresiones y consultas 
&lt;li&gt;Ubicación de llaves, paréntesis, corchetes, etc. 
&lt;li&gt;Espaciado alrededor de palabras clave y operadores 
&lt;li&gt;Espaciado entre líneas 
&lt;li&gt;Ubicación de parámetros en llamadas y declaraciones de métodos 
&lt;li&gt;Ordenación de elementos de una clase 
&lt;li&gt;Formateo de documentación de elementos y archivos 
&lt;li&gt;Nombrado de campos y variables 
&lt;li&gt;Uso de tipos integrados 
&lt;li&gt;Uso de modificadores de acceso 
&lt;li&gt;Contenidos permitidos en archivos 
&lt;li&gt;Texto de depuración&lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;&lt;a href="http://bp2.blogger.com/_O9D62hXq-ng/SDfw785OpWI/AAAAAAAAAfQ/6aQf0wCm2Mw/s1600-h/sourceanalysis.png"&gt;&lt;img id="BLOGGER_PHOTO_ID_5203892807199008098" style="FLOAT:right;MARGIN:0px 0px 10px 10px;CURSOR:hand;" alt="Microsoft Source Analysis integrado en VS2005" src="http://bp2.blogger.com/_O9D62hXq-ng/SDfw785OpWI/AAAAAAAAAfQ/6aQf0wCm2Mw/s400/sourceanalysis.png" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;Tras su descarga e instalación, que puede &lt;a title="[ING] Descarga de Microsoft Source Analysis" href="https://code.msdn.microsoft.com/Release/ProjectReleases.aspx?ProjectName=sourceanalysis"&gt;&lt;font color="#35537a"&gt;realizarse desde esta dirección&lt;/font&gt;&lt;/a&gt;, la herramienta se integra en Visual Studio 2005 y 2008, aunque también puede utilizarse desde la línea de comandos o MSBuild.&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=86667" 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/vs2008/default.aspx">vs2008</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/herramientas/default.aspx">herramientas</category></item><item><title>Inicializadores de colecciones en C#</title><link>http://geeks.ms/blogs/jmaguilar/archive/2008/04/28/inicializadores-de-colecciones-en-c.aspx</link><pubDate>Mon, 28 Apr 2008 18:22:00 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:84412</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=84412</wfw:commentRss><comments>http://geeks.ms/blogs/jmaguilar/archive/2008/04/28/inicializadores-de-colecciones-en-c.aspx#comments</comments><description>&lt;p&gt;&lt;a href="http://bp2.blogger.com/_O9D62hXq-ng/R-FiMyDcDQI/AAAAAAAAATY/S7lYsJZlPMk/s1600-h/csharp.jpg"&gt;&lt;img id="BLOGGER_PHOTO_ID_5179529018186927362" style="FLOAT:right;MARGIN:0px 0px 10px 10px;CURSOR:hand;" alt="" src="http://bp2.blogger.com/_O9D62hXq-ng/R-FiMyDcDQI/AAAAAAAAATY/S7lYsJZlPMk/s200/csharp.jpg" border="0" /&gt;&lt;/a&gt;Días atrás hablaba de las formas de &lt;a href="http://www.variablenotfound.com/2008/03/inicializacin-rpida-de-objetos-en-c-30.html"&gt;&lt;font color="#35537a"&gt;inicialización de objetos que nos proporcionaban las últimas versiones de C# y VB.Net&lt;/font&gt;&lt;/a&gt;, que permitían asignar valores a miembros de instancia de forma muy compacta, legible y cómoda.&lt;br /&gt;&lt;br /&gt;C# 3.0 nos trae otra sorpresa, también relacionada con el establecimiento de valores iniciales de elementos: los inicializadores de colecciones. Aunque esta característica también estaba prevista para VB.Net 9.0, al final fue desplazada a futuras versiones por problemas de tiempo.&lt;br /&gt;&lt;br /&gt;Para inicializar una colección, hasta ahora era necesario en primer lugar crear la clase correspondiente para, a continuación, realizar sucesivas invocaciones al método &lt;code&gt;Add()&lt;/code&gt; con cada uno de los elementos a añadir:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt; List&amp;lt;string&amp;gt; ls = new List&amp;lt;string&amp;gt;();&lt;br /&gt; ls.Add(&amp;quot;Uno&amp;quot;);&lt;br /&gt; ls.Add(&amp;quot;Dos&amp;quot;);&lt;br /&gt; ls.Add(&amp;quot;Tres&amp;quot;);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;C# 3.0 permite una alternativa mucho más elegante y rápida de codificar, simplemente se introducen los elementos a añadir a la colección entre llaves (como se hacía con los inicializadores de arrays o los nuevos inicializadores de objetos), separados por comas, como en el siguiente ejemplo:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt; List&amp;lt;string&amp;gt; ls = &lt;br /&gt;     new List&amp;lt;string&amp;gt;() { &amp;quot;Uno&amp;quot;, &amp;quot;Dos&amp;quot;, &amp;quot;Tres&amp;quot; };&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Si desensamblamos el ejecutable resultante, podremos ver que es el compilador el que ha añadido por nosotros los &lt;code&gt;Add()&lt;/code&gt; de cada uno de los elementos después de instanciar la colección:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt;&lt;br /&gt; newobj   instance void class &lt;br /&gt;          [mscorlib]System.Collections.Generic.List`1&amp;lt;string&amp;gt;::.ctor()&lt;br /&gt; stloc.s  &amp;#39;&amp;lt;&amp;gt;g__initLocal0&amp;#39;&lt;br /&gt; ldloc.s  &amp;#39;&amp;lt;&amp;gt;g__initLocal0&amp;#39;&lt;br /&gt; ldstr    &amp;quot;Uno&amp;quot;&lt;br /&gt; callvirt instance void class &lt;br /&gt;          [mscorlib]System.Collections.Generic.List`1&amp;lt;string&amp;gt;::&lt;strong&gt;Add&lt;/strong&gt;(!0)&lt;br /&gt; nop&lt;br /&gt; ldloc.s  &amp;#39;&amp;lt;&amp;gt;g__initLocal0&amp;#39;&lt;br /&gt; ldstr    &amp;quot;Dos&amp;quot;&lt;br /&gt; callvirt instance void class &lt;br /&gt;          [mscorlib]System.Collections.Generic.List`1&amp;lt;string&amp;gt;::&lt;strong&gt;Add&lt;/strong&gt;(!0)&lt;br /&gt; nop&lt;br /&gt; ldloc.s  &amp;#39;&amp;lt;&amp;gt;g__initLocal0&amp;#39;&lt;br /&gt; ldstr    &amp;quot;Tres&amp;quot;&lt;br /&gt; callvirt instance void class &lt;br /&gt;          [mscorlib]System.Collections.Generic.List`1&amp;lt;string&amp;gt;::&lt;strong&gt;Add&lt;/strong&gt;(!0)&lt;br /&gt; nop&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Uniendo esto ahora con los &lt;a href="http://www.variablenotfound.com/2008/03/inicializacin-rpida-de-objetos-en-c-30.html"&gt;&lt;font color="#35537a"&gt;inicializadores de objetos&lt;/font&gt;&lt;/a&gt; que ya tratamos un post anterior, fijaos en la potencia del resultado:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt; List&amp;lt;Persona&amp;gt; lp = new List&amp;lt;Persona&amp;gt;&lt;br /&gt; {&lt;br /&gt;   new Persona { Nombre=&amp;quot;Juan&amp;quot;, Edad=34 },&lt;br /&gt;   new Persona { Nombre=&amp;quot;Luis&amp;quot;, Edad=53 },&lt;br /&gt;   new Persona { Nombre=&amp;quot;José&amp;quot;, Edad=23 }&lt;br /&gt; };&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;Efectivamente, cada elemento es una nueva instancia de la clase Persona, con las propiedades que nos interesan inicializadas de forma directa. De hacerlo con los métodos tradicionales, para conseguir el mismo resultado deberíamos utilizar muuuchas más líneas de código.&lt;br /&gt;&lt;br /&gt;Otro ejemplo que demuestra aún más la potencia de esta característica:&lt;br /&gt;&lt;/p&gt;&lt;pre&gt;&lt;code&gt; var nums = new SortedList&lt;br /&gt; {&lt;br /&gt;   { 34, &amp;quot;Treinta y cuatro&amp;quot; },&lt;br /&gt;   { 12, &amp;quot;Doce&amp;quot; },&lt;br /&gt;   { 3, &amp;quot;Tres&amp;quot; }&lt;br /&gt; };&lt;br /&gt; foreach (var e in nums)&lt;br /&gt;   Console.WriteLine(e.Key + &amp;quot; &amp;quot; + e.Value);&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;br /&gt;En el código anterior podemos ver, primero, el uso de variables locales de tipo implícito, para ahorrarnos tener que escribir más de la cuenta. En segundo lugar, se muestra cómo se inicializa una colección cuyo método &lt;code&gt;Add()&lt;/code&gt; requiere dos parámetros. En el caso de un &lt;code&gt;SortedList&amp;lt;TKey, TValue&amp;gt;&lt;/code&gt;, su método &lt;code&gt;Add()&lt;/code&gt; requiere la clave de ordenación y el valor del elemento.&lt;br /&gt;&lt;br /&gt;(Obviamente, el resultado de la ejecución del código anterior será la lista ordenada por su valor numérico (Key))&lt;br /&gt;&lt;br /&gt;En conclusión, se trata de otra de las innumerables ventajas que nos ofrece la nueva versión de C# destinadas a evitarnos pulsaciones innecesarias, y a la que seguro le daremos uso.&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=84412" 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></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>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></channel></rss>