<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.kartones.net/~d/styles/itemcontent.css"?><rss 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/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>Jad Engine Blog</title><link>http://kartones.net/blogs/jadengine/default.aspx</link><description>My personal blog about C#, XNA and AI programming.</description><dc:language>en</dc:language><generator>CommunityServer 2007 SP2 (Build: 20611.960)</generator><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.kartones.net/JadEngineBlog" /><feedburner:info uri="jadengineblog" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><title>Rotor’scope – The Secret of Endless Energy</title><link>http://feeds.kartones.net/~r/JadEngineBlog/~3/P2rolIqJdiI/rotor-scope-the-secret-of-endless-energy.aspx</link><pubDate>Sat, 13 Feb 2010 18:25:00 GMT</pubDate><guid isPermaLink="false">b86c0850-82e5-42ed-a9d8-bde9e8f94ec1:50728</guid><dc:creator>Vicente</dc:creator><slash:comments>0</slash:comments><comments>http://kartones.net/blogs/jadengine/archive/2010/02/13/rotor-scope-the-secret-of-endless-energy.aspx#comments</comments><description>&lt;p&gt;Así se llama el último juego del estudio español &lt;a href="http://www.nivel21.net/"&gt;Nivel21&lt;/a&gt;, desarrollado en XNA y ganador del segundo premio en el concurso &lt;a href="http://www.dreambuildplay.com/main/default.aspx"&gt;Dream-Build-Play Challenge 09&lt;/a&gt; de Microsoft. Rotor’Scope es un juego de puzzles muy original, con una historia y trama bastante trabajadas para que no sea un simplemente “me paso este puzzle, me paso este otro puzzle,…”. La verdad que quería nombrarlo en el blog por varios motivos:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Muestra que hacer un juego de calidad no es cuestión de la plataforma, lenguaje,… si no de las ganas que se tengan. Está claro que las herramientas ayudan, y soy de la opinión que C# + XNA es una combinación realmente productiva, pero que nadie se engañe diciendo: &amp;quot;es que este lenguaje/framework/engine/… no me da suficiente rendimiento&amp;quot;. Ja, excusas.&lt;/li&gt;    &lt;li&gt;Ahora mismo es uno de los juegos más trabajados de los XBox Live Indie Games, y ciertamente tiene el nivel suficiente para ser un juego de XBLA.&lt;/li&gt;    &lt;li&gt;Han creado un motor open source llamado &lt;a href="http://www.nivel21.net/Technology/tomahawkfull.html"&gt;Tomahawk&lt;/a&gt; que es una de las mejores herramientas disponibles actualmente para hacer un juego con XNA. Se nota que la gente que lo ha hecho tiene experiencia profesional.&lt;/li&gt;    &lt;li&gt;Han dado un ejemplo de “no atarse a las limitaciones” implementando &lt;a href="http://www.nivel21.net/Technology/indiefbfull.html"&gt;conectividad con Facebook&lt;/a&gt; cuando técnicamente no se puede. No solo Facebook, Twitter y similares son unas herramientas de promoción increíbles entre los compradores, además han dado mucho de que hablar entre los desarrolladores con esta característica.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Así que nada, si os gustan los puzzles os animo a que &lt;strike&gt;le echéis un vistazo&lt;/strike&gt; lo compréis en la XBox360. Aquí os dejo el enlance al &lt;a href="http://marketplace.xbox.com/en-US/games/media/66acd000-77fe-1000-9115-d8025855042f/"&gt;marketplace&lt;/a&gt; y unas capturas sacadas de su &lt;a href="http://www.rotorscope-game.com"&gt;web&lt;/a&gt;:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://kartones.net/blogs/jadengine/rotorscope_screenshot_01_53CA9C3E.png"&gt;&lt;img src="http://kartones.net/blogs/jadengine/rotorscope_screenshot_01_thumb_1C24B583.png" style="border:0px none;display:inline;" title="rotorscope_screenshot_01" alt="rotorscope_screenshot_01" width="540" border="0" height="320" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://kartones.net/blogs/jadengine/rotorscope_screenshot_06_1C0469E9.png"&gt;&lt;img src="http://kartones.net/blogs/jadengine/rotorscope_screenshot_06_thumb_7FD35F63.png" style="border:0px none;display:inline;" title="rotorscope_screenshot_06" alt="rotorscope_screenshot_06" width="540" border="0" height="315" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;&lt;a href="http://kartones.net/blogs/jadengine/rotorscope_screenshot_05_7E0247F5.png"&gt;&lt;img src="http://kartones.net/blogs/jadengine/rotorscope_screenshot_05_thumb_2F0136FC.png" style="border:0px none;display:inline;" title="rotorscope_screenshot_05" alt="rotorscope_screenshot_05" width="540" border="0" height="306" /&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://kartones.net/aggbug.aspx?PostID=50728" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JadEngineBlog/~4/P2rolIqJdiI" height="1" width="1"/&gt;</description><category domain="http://kartones.net/blogs/jadengine/archive/tags/XNA/default.aspx">XNA</category><category domain="http://kartones.net/blogs/jadengine/archive/tags/Videojuegos/default.aspx">Videojuegos</category><feedburner:origLink>http://kartones.net/blogs/jadengine/archive/2010/02/13/rotor-scope-the-secret-of-endless-energy.aspx</feedburner:origLink></item><item><title>dynamic (III): DynamicObject</title><link>http://feeds.kartones.net/~r/JadEngineBlog/~3/bBialBiiDDY/dynamic-iii-dynamicobject.aspx</link><pubDate>Wed, 20 Jan 2010 17:33:00 GMT</pubDate><guid isPermaLink="false">b86c0850-82e5-42ed-a9d8-bde9e8f94ec1:50684</guid><dc:creator>Vicente</dc:creator><slash:comments>2</slash:comments><comments>http://kartones.net/blogs/jadengine/archive/2010/01/20/dynamic-iii-dynamicobject.aspx#comments</comments><description>&lt;p&gt;Puede que se dé la ocasión que busquemos un comportamiento parecido al de &lt;a href="http://kartones.net/blogs/jadengine/archive/2010/01/07/dynamic-ii-expandoobject.aspx"&gt;ExpandoObject&lt;/a&gt; pero necesitemos cambiar alguna cosa. Por ejemplo, el siguiente código lanza una &lt;a href="http://msdn.microsoft.com/en-us/library/microsoft.csharp.runtimebinder.runtimebinderexception%28VS.100%29.aspx"&gt;RuntimeBinderException&lt;/a&gt; ya que la propiedad Name no ha sido asignada con anterioridad.&lt;/p&gt;
  &lt;div class="csharpcode"&gt;   
&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;namespace&lt;/span&gt; ConsoleApplication2&lt;/pre&gt;
  
&lt;pre&gt;{&lt;/pre&gt;
  
&lt;pre class="alt"&gt;    &lt;span class="kwrd"&gt;class&lt;/span&gt; Program&lt;/pre&gt;
  
&lt;pre&gt;    {&lt;/pre&gt;
  
&lt;pre class="alt"&gt;        &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)&lt;/pre&gt;
  
&lt;pre&gt;        {&lt;/pre&gt;
  
&lt;pre class="alt"&gt;            dynamic expando = &lt;span class="kwrd"&gt;new&lt;/span&gt; ExpandoObject();&lt;/pre&gt;
  
&lt;pre&gt;            Console.WriteLine(expando.Name);&lt;/pre&gt;
  
&lt;pre class="alt"&gt;        }&lt;/pre&gt;
  
&lt;pre&gt;    }&lt;/pre&gt;
  
&lt;pre class="alt"&gt;}&lt;/pre&gt;
&lt;/div&gt;


&lt;p&gt;Pero, ¿y si quisiéramos que cuando no exista un miembro se devuelva null en vez de una excepción? Con ExpandoObject esto es imposible, pero la buena noticia es que podemos hacer nuestro propio ExpandoObject si implementamos la interfaz &lt;a href="http://msdn.microsoft.com/en-us/library/system.dynamic.idynamicmetaobjectprovider%28VS.100%29.aspx"&gt;IDynamicMetaObjectProvider&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Mirando la información de la MSDN y ojeando en internet descubrimos dos cosas:&lt;/p&gt;

&lt;p&gt;a) Implementar IDynamicMetaObjectProvider es bastante difícil.&lt;/p&gt;

&lt;p&gt;b) Microsoft ha proporcionado una clase que proporciona una implementación por defecto de IDynamicMetaObjectProvider: &lt;a href="http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject%28VS.100%29.aspx"&gt;DynamicObject&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;DynamicObject proporciona un montón de métodos de la forma “TrySomething” que son los que se usan en la ligadura dinámica. Por ejemplo, &lt;a href="http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject.trygetmember%28VS.100%29.aspx"&gt;TryGetMember&lt;/a&gt; y &lt;a href="http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject.trysetmember%28VS.100%29.aspx"&gt;TrySetMember&lt;/a&gt; nos permiten definir qué ocurre cuando se accede a un miembro de la clase de forma dinámica. Con esto ya podemos hacer nuestra propia versión de ExpandoObject:&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  
&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;class&lt;/span&gt; MyExpando : DynamicObject&lt;/pre&gt;
  
&lt;pre&gt;{&lt;/pre&gt;
  
&lt;pre class="alt"&gt;    &lt;span class="kwrd"&gt;private&lt;/span&gt; Dictionary&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;object&lt;/span&gt;&amp;gt; members = &lt;span class="kwrd"&gt;new&lt;/span&gt; Dictionary&amp;lt;&lt;span class="kwrd"&gt;string&lt;/span&gt;, &lt;span class="kwrd"&gt;object&lt;/span&gt;&amp;gt;();&lt;/pre&gt;
  
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
  
&lt;pre class="alt"&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; TryGetMember(GetMemberBinder binder, &lt;span class="kwrd"&gt;out&lt;/span&gt; &lt;span class="kwrd"&gt;object&lt;/span&gt; result)&lt;/pre&gt;
  
&lt;pre&gt;    {&lt;/pre&gt;
  
&lt;pre class="alt"&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (&lt;span class="kwrd"&gt;this&lt;/span&gt;.members.TryGetValue(binder.Name, &lt;span class="kwrd"&gt;out&lt;/span&gt; result))&lt;/pre&gt;
  
&lt;pre&gt;        {&lt;/pre&gt;
  
&lt;pre class="alt"&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;/pre&gt;
  
&lt;pre&gt;        }&lt;/pre&gt;
  
&lt;pre class="alt"&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;/pre&gt;
  
&lt;pre&gt;        {&lt;/pre&gt;
  
&lt;pre class="alt"&gt;            &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;/pre&gt;
  
&lt;pre&gt;        }&lt;/pre&gt;
  
&lt;pre class="alt"&gt;    }&lt;/pre&gt;
  
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
  
&lt;pre class="alt"&gt;    &lt;span class="kwrd"&gt;public&lt;/span&gt; &lt;span class="kwrd"&gt;override&lt;/span&gt; &lt;span class="kwrd"&gt;bool&lt;/span&gt; TrySetMember(SetMemberBinder binder, &lt;span class="kwrd"&gt;object&lt;/span&gt; &lt;span class="kwrd"&gt;value&lt;/span&gt;)&lt;/pre&gt;
  
&lt;pre&gt;    {&lt;/pre&gt;
  
&lt;pre class="alt"&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (members.ContainsKey(binder.Name))&lt;/pre&gt;
  
&lt;pre&gt;        {&lt;/pre&gt;
  
&lt;pre class="alt"&gt;            members[binder.Name] = &lt;span class="kwrd"&gt;value&lt;/span&gt;;&lt;/pre&gt;
  
&lt;pre&gt;        }&lt;/pre&gt;
  
&lt;pre class="alt"&gt;        &lt;span class="kwrd"&gt;else&lt;/span&gt;&lt;/pre&gt;
  
&lt;pre&gt;        {&lt;/pre&gt;
  
&lt;pre class="alt"&gt;            members.Add(binder.Name, &lt;span class="kwrd"&gt;value&lt;/span&gt;);&lt;/pre&gt;
  
&lt;pre&gt;        }&lt;/pre&gt;
  
&lt;pre class="alt"&gt;&amp;nbsp;&lt;/pre&gt;
  
&lt;pre&gt;        &lt;span class="kwrd"&gt;return&lt;/span&gt; &lt;span class="kwrd"&gt;true&lt;/span&gt;;&lt;/pre&gt;
  
&lt;pre class="alt"&gt;    }&lt;/pre&gt;
  
&lt;pre&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Lo que hacemos es muy parecido a lo que &lt;a href="http://kartones.net/blogs/jadengine/archive/2010/01/07/dynamic-ii-expandoobject.aspx"&gt;intuíamos&lt;/a&gt; que hacía internamente ExpandoObject: cuando se asigna un valor (TrySetMember) este se guarda en un diccionario, y luego cuando se recupera (TryGetMember) se mira si existe y en caso de que no exista se devuelve null (en vez de una excepción). Para comprobar que todo funciona bien, un pequeño programa de prueba:&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  
&lt;pre class="alt"&gt;&lt;span class="kwrd"&gt;class&lt;/span&gt; Program&lt;/pre&gt;
  
&lt;pre&gt;{&lt;/pre&gt;
  
&lt;pre class="alt"&gt;    &lt;span class="kwrd"&gt;static&lt;/span&gt; &lt;span class="kwrd"&gt;void&lt;/span&gt; Main(&lt;span class="kwrd"&gt;string&lt;/span&gt;[] args)&lt;/pre&gt;
  
&lt;pre&gt;    {&lt;/pre&gt;
  
&lt;pre class="alt"&gt;        dynamic expando = &lt;span class="kwrd"&gt;new&lt;/span&gt; MyExpando();&lt;/pre&gt;
  
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
  
&lt;pre class="alt"&gt;        expando.FirstName = &lt;span class="str"&gt;&amp;quot;Hola&amp;quot;&lt;/span&gt;;&lt;/pre&gt;
  
&lt;pre&gt;        Console.WriteLine(expando.FirstName);&lt;/pre&gt;
  
&lt;pre class="alt"&gt;&amp;nbsp;&lt;/pre&gt;
  
&lt;pre&gt;        &lt;span class="kwrd"&gt;if&lt;/span&gt; (expando.LastName == &lt;span class="kwrd"&gt;null&lt;/span&gt;)&lt;/pre&gt;
  
&lt;pre class="alt"&gt;        {&lt;/pre&gt;
  
&lt;pre&gt;            Console.WriteLine(&lt;span class="str"&gt;&amp;quot;null&amp;quot;&lt;/span&gt;);&lt;/pre&gt;
  
&lt;pre class="alt"&gt;        }&lt;/pre&gt;
  
&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
  
&lt;pre class="alt"&gt;        Console.ReadKey();&lt;/pre&gt;
  
&lt;pre&gt;    }&lt;/pre&gt;
  
&lt;pre class="alt"&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;La salida es “Hola” en una línea y “null” en la siguiente. Si en cambio en el else del TryGetMember hubiéramos escrito un “return false;” el comportamiento sería idéntico al de ExpandoObject: RuntimeBinderException.&lt;/p&gt;

&lt;p&gt;En el próximo post retomaré el experimento de &lt;a href="http://kartones.net/blogs/jadengine/archive/2009/02/09/implementando-el-reglamendo-de-un-rpg.aspx"&gt;librería para CRPGs&lt;/a&gt; y como DynamicObject simplifica la implementación del patrón &lt;a href="http://en.wikipedia.org/wiki/Prototype_pattern"&gt;prototype&lt;/a&gt;.&lt;/p&gt;
&lt;img src="http://kartones.net/aggbug.aspx?PostID=50684" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JadEngineBlog/~4/bBialBiiDDY" height="1" width="1"/&gt;</description><category domain="http://kartones.net/blogs/jadengine/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://kartones.net/blogs/jadengine/archive/tags/dynamic/default.aspx">dynamic</category><feedburner:origLink>http://kartones.net/blogs/jadengine/archive/2010/01/20/dynamic-iii-dynamicobject.aspx</feedburner:origLink></item><item><title>Dynamic (II): ExpandoObject</title><link>http://feeds.kartones.net/~r/JadEngineBlog/~3/s1PZ-HMEz6Q/dynamic-ii-expandoobject.aspx</link><pubDate>Thu, 07 Jan 2010 16:00:01 GMT</pubDate><guid isPermaLink="false">b86c0850-82e5-42ed-a9d8-bde9e8f94ec1:50647</guid><dc:creator>Vicente</dc:creator><slash:comments>3</slash:comments><comments>http://kartones.net/blogs/jadengine/archive/2010/01/07/dynamic-ii-expandoobject.aspx#comments</comments><description>&lt;p&gt;El uso de dynamic no está solamente limitado a crear variables, métodos, lambdas,… con tipos dinámicos, si no que se ha añadido un nuevo namespace a C# 4.0 llamado &lt;a href="http://msdn.microsoft.com/en-us/library/system.dynamic%28VS.100%29.aspx"&gt;System.Dynamic&lt;/a&gt; que contiene diferentes clases e interfaces relacionadas con la resolución de operaciones dinámicas (las clases de nombre XYZBinder). A parte de estas clases hay dos especiales que merece la pena comentar con más detalle: &lt;a href="http://msdn.microsoft.com/en-us/library/system.dynamic.expandoobject%28VS.100%29.aspx"&gt;ExpandoObject&lt;/a&gt; y &lt;a href="http://msdn.microsoft.com/en-us/library/system.dynamic.dynamicobject%28VS.100%29.aspx"&gt;DynamicObject&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;ExpandoObject está definido de la siguiente manera en la MSDN:&lt;/p&gt;  &lt;p&gt;&lt;i&gt;Represents an object whose members can be dynamically added and removed at run time.&lt;/i&gt;&lt;/p&gt;  &lt;p&gt;Básicamente ExpandoObject es un objeto al que se le pueden añadir nuevas propiedades, métodos, eventos,… en tiempo de ejecución. Vamos a ver cómo. Si declaramos una variable de tipo ExpandoObject podemos observar que no tiene casi métodos o propiedades:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://kartones.net/blogs/jadengine/expando_4984E4F5.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:block;float:none;margin-left:auto;border-top:0px;margin-right:auto;border-right:0px;" title="expando" border="0" alt="expando" src="http://kartones.net/blogs/jadengine/expando_thumb_1C8F821A.png" width="481" height="369" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;La “magia” ocurre cuando declaramos un ExpandoObject como dynamic:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://kartones.net/blogs/jadengine/expando2_03640215.png"&gt;&lt;img style="border-bottom:0px;border-left:0px;display:block;float:none;margin-left:auto;border-top:0px;margin-right:auto;border-right:0px;" title="expando2" border="0" alt="expando2" src="http://kartones.net/blogs/jadengine/expando2_thumb_61982983.png" width="485" height="312" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Intellisense nos avisa que como expando es una variable dinámica, todas las operaciones se resolverán en tiempo de ejecución. Lo cual nos va a permitir hacer cosas como esta:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://kartones.net/blogs/jadengine/expando3_453AC196.png"&gt;&lt;img style="border-right-width:0px;display:block;float:none;border-top-width:0px;border-bottom-width:0px;margin-left:auto;border-left-width:0px;margin-right:auto;" title="expando3" border="0" alt="expando3" src="http://kartones.net/blogs/jadengine/expando3_thumb_416CF6F9.png" width="748" height="558" /&gt;&lt;/a&gt; &lt;/p&gt;  &lt;p&gt;Era de esperar que el código compilara ya que usando una variable del tipo dynamic casi cualquier cosa vale. Pero lo que no está tan claro es porque el código ejecuta, ya que como vimos en la primera captura ExpandoObject no tiene una propiedad llamada Lives ni un método llamado SomeMethod que acepte un int y devuelve un string. Si volvemos a la MSDN nos encontramos que la clase está declarada de la siguiente manera:&lt;/p&gt;  &lt;p&gt;&lt;em&gt;public sealed class ExpandoObject : IDynamicMetaObjectProvider, IDictionary&amp;lt;string, Object&amp;gt;, ICollection&amp;lt;KeyValuePair&amp;lt;string, Object&amp;gt;&amp;gt;, IEnumerable&amp;lt;KeyValuePair&amp;lt;string, Object&amp;gt;&amp;gt;, IEnumerable, INotifyPropertyChanged&lt;/em&gt;&lt;/p&gt;  &lt;p&gt;ExpandoObject implementa muchas interfaces, pero la única “especial” es &lt;a href="http://msdn.microsoft.com/en-us/library/system.dynamic.idynamicmetaobjectprovider%28VS.100%29.aspx"&gt;IDynamicMetaObjectProvider&lt;/a&gt;, así que podemos asumir que es la que está relacionada con la “magia” de antes. De todas formas también vemos que ExpandoObject se comporta como un IDictionary&amp;lt;string, object&amp;gt;, así que es más o menos fácil imaginarse que puede estar pasando internamente: cuando se asigna un valor a una propiedad que no existe, de alguna forma que desconocemos se guarda el nombre de la propiedad y el valor en un diccionario interno y cuando se lee la propiedad este valor se recupera del mismo. Nada muy sorprendente, se podría incluso pensar que esto es solo “syntactic sugar” que traduce &lt;b&gt;expando.Lives = 3&lt;/b&gt; a &lt;b&gt;expando.Add(“Lives”, 3)&lt;/b&gt; o &lt;b&gt;expando[“Lives”] = 3&lt;/b&gt; (no lo es, pero lo parece).&lt;/p&gt;  &lt;p&gt;¿Y cuándo usar ExpandoObject? Pues ExpandoObject debería usarse en los sitios que se tenga un Dictionary&amp;lt;string, object&amp;gt;, por ejemplo cuando se leen pares de clave-valor de ficheros de configuración, o cuando se necesite una clase a la que se le pueda añadir funcionalidad en tiempo de ejecución, lo cual es más raro, pero hay casos de sistemas que requieren esta flexibilidad y las alternativas a usar ExpandoObject suelen tener una sintaxis horrorosa y no ofrecen casi ninguna ventaja.&lt;/p&gt;  &lt;p&gt;Y finalmente, ¿y sí queremos modificar el comportamiento de ExpandoObject? Pues desgraciadamente no se puede, pero la buena noticia es que podemos hacer nuestra propia versión de ExpandoObject si implementamos IDynamicMetaObjectProvider. Pero eso lo dejo para el próximo post.&lt;/p&gt;&lt;img src="http://kartones.net/aggbug.aspx?PostID=50647" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JadEngineBlog/~4/s1PZ-HMEz6Q" height="1" width="1"/&gt;</description><category domain="http://kartones.net/blogs/jadengine/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://kartones.net/blogs/jadengine/archive/tags/dynamic/default.aspx">dynamic</category><feedburner:origLink>http://kartones.net/blogs/jadengine/archive/2010/01/07/dynamic-ii-expandoobject.aspx</feedburner:origLink></item><item><title>Novedades C# 4.0: dynamic</title><link>http://feeds.kartones.net/~r/JadEngineBlog/~3/B3mZGEfvkr0/novedades-c-4-0-dynamic.aspx</link><pubDate>Tue, 29 Dec 2009 12:24:00 GMT</pubDate><guid isPermaLink="false">b86c0850-82e5-42ed-a9d8-bde9e8f94ec1:50635</guid><dc:creator>Vicente</dc:creator><slash:comments>0</slash:comments><comments>http://kartones.net/blogs/jadengine/archive/2009/12/29/novedades-c-4-0-dynamic.aspx#comments</comments><description>&lt;p&gt;NET está haciendo una apuesta muy fuerte por los lenguajes dinámicos y sus características. Primero con toda la infraestructura del DLR (Dynamic Language Runtime), IronRuby, IronPython,… y ahora añadiendo mejoras en la interacción de estos nuevos lenguajes con C# a través de la palabra reservada &lt;b&gt;dynamic&lt;/b&gt;.
&lt;/p&gt;&lt;p&gt;dynamic es un nuevo tipo, pero es un tipo especial que se resuelve en tiempo de ejecución y no en tiempo de compilación, es decir, podemos hacer algo como:
&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas;font-size:9pt;"&gt;&lt;span style="color:blue;"&gt;dynamic&lt;/span&gt; a = GetDynamicObject();
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas;font-size:9pt;"&gt;a.SomeMethod();
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Y realmente, podríamos ejecutar cualquier cosa sobre &lt;b&gt;a&lt;/b&gt;, porque el Visual Studio no tiene ni idea de que es a hasta que se ejecute este código (vamos, que cuando le damos al punto no sale nada en el Intellisense ;) ). Esto seguramente le resultará raro a mucha gente, ya que por lo general los programadores de C# estamos acostumbrados al tipado estático (los tipos se saben en tiempo de compilación) pero si queremos poder interactuar con lenguajes dinámicos necesitamos que C# soporte el tipado dinámico.
&lt;/p&gt;&lt;p&gt;Hay que tener en cuenta que &lt;b&gt;dynamic&lt;/b&gt; no es lo mismo que &lt;b&gt;object&lt;/b&gt; ni que &lt;b&gt;var&lt;/b&gt;. Por ejemplo, esto compila con dynamic:
&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas;font-size:9pt;"&gt;&lt;span style="color:blue;"&gt;dynamic&lt;/span&gt; a = &lt;span&gt;&amp;quot;hola&amp;quot;&lt;/span&gt;;
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas;font-size:9pt;"&gt;a.SomeMethod();
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas;font-size:9pt;"&gt;&lt;span style="color:blue;"&gt;int&lt;/span&gt; i = a;
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Como &lt;b&gt;a&lt;/b&gt; es dinámico, todas las operaciones en las que &lt;b&gt;a&lt;/b&gt; esté involucrado se resolverán en tiempo de ejecución (a pesar de que claramente las dos van a petar). Si hacemos esto:
&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas;font-size:9pt;"&gt;&lt;span style="color:blue;"&gt;dynamic&lt;/span&gt; num = &lt;span style="color:brown;"&gt;3&lt;/span&gt;;
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas;font-size:9pt;"&gt;&lt;span style="color:blue;"&gt;var&lt;/span&gt; result = num + &lt;span style="color:brown;"&gt;5&lt;/span&gt;;
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Y usamos el visual para ver el tipo de &lt;b&gt;result&lt;/b&gt;, nos saldrá que es &lt;b&gt;dynamic&lt;/b&gt;, ya que como &lt;b&gt;num&lt;/b&gt; es &lt;b&gt;dynamic&lt;/b&gt;, a pesar de que tiene un entero dentro y le estamos sumando otro entero, toda la operación pasa a ser dinámica. Así mismo &lt;b&gt;dynamic&lt;/b&gt; no solo puede usarse para declarar tipos aislados, sino también para parámetros en funciones. Esto es perfectamente legal:
&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas;font-size:9pt;"&gt;&lt;span style="color:blue;"&gt;public&lt;/span&gt;
			&lt;span style="color:blue;"&gt;void&lt;/span&gt; Method(&lt;span style="color:blue;"&gt;dynamic&lt;/span&gt; argument)
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas;font-size:9pt;"&gt;{
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas;font-size:9pt;"&gt;&amp;nbsp; argument.DoSomething();
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas;font-size:9pt;"&gt;}
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;En tiempo de compilación funcionará, y luego en tiempo de ejecución dependerá de si el objeto &lt;b&gt;argument&lt;/b&gt; tiene un método llamado &lt;b&gt;DoSomething&lt;/b&gt; sin parámetros. Si no es el caso recibiremos una &lt;b&gt;RuntimeException&lt;/b&gt; al llegar a esa línea de código. Esto también es legal en tiempo de compilación:
&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:Consolas;font-size:9pt;"&gt;&lt;span&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;dynamic&lt;/span&gt;, &lt;span style="color:blue;"&gt;bool&lt;/span&gt;&amp;gt; func = x =&amp;gt; x.BoolenValue;
&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;p&gt;Donde habríamos declarado un delegado que recibe un tipo dinámico y devuelve un bool.
&lt;/p&gt;&lt;p&gt;La verdad que para C# &lt;b&gt;dynamic&lt;/b&gt; es un arma de doble filo: por un lado te permite hacer aberraciones ya que cualquier cosa dinámica compila y todos los errores te los vas a encontrar en tiempo de ejecución. Pero por otro lado te permite hacer cosas que son muy difíciles (o engorrosas) de expresar con C# 3.0 y que en ciertas situaciones son muy útiles. En los próximos posts explicaré más en detalle nuevas características de &lt;b&gt;dynamic&lt;/b&gt; y el DLR y como nos pueden ayudar a hacer sistemas muy flexibles en C#.
&lt;/p&gt;&lt;p&gt;Para más información: &lt;a href="http://msdn.microsoft.com/en-us/library/dd264736%28VS.100%29.aspx"&gt;http://msdn.microsoft.com/en-us/library/dd264736%28VS.100%29.aspx&lt;/a&gt;&lt;/p&gt;&lt;img src="http://kartones.net/aggbug.aspx?PostID=50635" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JadEngineBlog/~4/B3mZGEfvkr0" height="1" width="1"/&gt;</description><category domain="http://kartones.net/blogs/jadengine/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://kartones.net/blogs/jadengine/archive/tags/dynamic/default.aspx">dynamic</category><feedburner:origLink>http://kartones.net/blogs/jadengine/archive/2009/12/29/novedades-c-4-0-dynamic.aspx</feedburner:origLink></item><item><title>MVP otro año más</title><link>http://feeds.kartones.net/~r/JadEngineBlog/~3/-_LZnpE91f0/mvp-otro-a-241-o-m-225-s.aspx</link><pubDate>Mon, 06 Jul 2009 14:30:34 GMT</pubDate><guid isPermaLink="false">b86c0850-82e5-42ed-a9d8-bde9e8f94ec1:50180</guid><dc:creator>Vicente</dc:creator><slash:comments>1</slash:comments><comments>http://kartones.net/blogs/jadengine/archive/2009/07/06/mvp-otro-a-241-o-m-225-s.aspx#comments</comments><description>&lt;p&gt;Hace unos días recibí una noticia que la verdad me hacía mucha ilusión recibir: he sido renovado como MVP de DirectX/XNA :) Este es mi segundo año como MVP y estoy encantado de poder seguir participando en esta tecnología que personalmente creo que tiene mucho futuro (aunque los principios siempre sean difíciles).&lt;/p&gt;  &lt;p&gt;Además este año (que yo sepa) se nos unen como MVPs de DirectX/XNA dos personas que admiro muchísimo: &lt;a href="https://mvp.support.microsoft.com/profile/Ayucar"&gt;Iñaki Ayucar&lt;/a&gt; (¡otro español!) y &lt;a href="https://mvp.support.microsoft.com/profile=08938215-662E-45FA-B327-4E8755E07B6A"&gt;Promit Roy&lt;/a&gt;. ¡Enhorabuena a ambos!&lt;/p&gt;  &lt;p&gt;&lt;img style="border-bottom:0px;border-left:0px;display:inline;border-top:0px;border-right:0px;" title="mvplogo[1]" border="0" alt="mvplogo[1]" src="http://kartones.net/blogs/jadengine/mvplogo1_thumb_0E5E33BD.jpg" width="112" height="172" /&gt;&lt;/p&gt;&lt;img src="http://kartones.net/aggbug.aspx?PostID=50180" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JadEngineBlog/~4/-_LZnpE91f0" height="1" width="1"/&gt;</description><feedburner:origLink>http://kartones.net/blogs/jadengine/archive/2009/07/06/mvp-otro-a-241-o-m-225-s.aspx</feedburner:origLink></item><item><title>El patrón Singleton en C#</title><link>http://feeds.kartones.net/~r/JadEngineBlog/~3/KOyWmLZC-Wc/el-patr-243-n-singleton-en-c.aspx</link><pubDate>Wed, 20 May 2009 15:21:00 GMT</pubDate><guid isPermaLink="false">b86c0850-82e5-42ed-a9d8-bde9e8f94ec1:50052</guid><dc:creator>Vicente</dc:creator><slash:comments>5</slash:comments><comments>http://kartones.net/blogs/jadengine/archive/2009/05/20/el-patr-243-n-singleton-en-c.aspx#comments</comments><description>&lt;p&gt;Una de las cosas que creo es importante cuando usas un lenguaje es entender como funciona por dentro. Por ejemplo es cierto que C# se parece mucho a Java pero a bajo nivel presentan muchas diferencias de filosofía y diseño que creo son importantes de entender para hacer un uso eficaz del mismo. Algo similar ocurre cuando alguien que está acostumbrado a C++ se pasa a C#, muchas veces piensa que es un C++ “fácil” (sin punteros, sin gestión de memoria) y luego se queja de que su rendimiento es mucho peor, que va lento,… cuando a veces todo esto es porque está usando C# como si fuera C++ y las cosas no funcionan así.&lt;/p&gt;
&lt;p&gt;Un ejemplo de libro de esta situación es la implementación del &lt;a href="http://en.wikipedia.org/wiki/Singleton_pattern"&gt;patrón Singleton&lt;/a&gt; en C#. Si buscáis un poco, en muchas páginas webs para implementar un Singleton lazy y thread-safe en Java/C++ se recomienda la siguiente implementación:&lt;/p&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;sealed&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;class&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Singleton&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;{&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Singleton&lt;/span&gt; instance = &lt;span style="COLOR:blue;"&gt;null&lt;/span&gt;;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;readonly&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;object&lt;/span&gt; padlock = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;object&lt;/span&gt;();&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Singleton()&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Singleton&lt;/span&gt; Instance&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;get&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (instance == &lt;span style="COLOR:blue;"&gt;null&lt;/span&gt;)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;lock&lt;/span&gt; (padlock)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;if&lt;/span&gt; (instance == &lt;span style="COLOR:blue;"&gt;null&lt;/span&gt;)&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; instance = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Singleton&lt;/span&gt;();&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; instance;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;}&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;La sintaxis es de C#, pero lo importante es la idea del if/lock/if. A esto se le llama &lt;a href="http://en.wikipedia.org/wiki/Double-checked_locking"&gt;double-checked-locking&lt;/a&gt; y por motivos bastante sutiles esa implementación no es totalmente thread-safe (más detalles &lt;a href="http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html"&gt;en este paper&lt;/a&gt;). El problema de thread-safe se puede solucionar haciendo la variable instance &lt;a href="http://en.wikipedia.org/wiki/Volatile_variable"&gt;volatile&lt;/a&gt; (a partir de la JDK 5.0 y Visual C++ 2005, ni idea en otros compiladores de C++).&lt;/p&gt;
&lt;p&gt;El problema es que como mucha gente de Java/C++ se ha acostumbrado a implementar el Singleton de esa manera, cuando llegan a C# hacen lo mismo. Pero resulta que en C# la implementación correcta es la siguiente:&lt;/p&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;sealed&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;class&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Singleton&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;{&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;readonly&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Singleton&lt;/span&gt; instance = &lt;span style="COLOR:blue;"&gt;new&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Singleton&lt;/span&gt;();&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; Singleton()&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Singleton()&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Singleton&lt;/span&gt; Instance&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;get&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;return&lt;/span&gt; instance;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;}&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Visto así por encima, esa implementación no parece ni lazy, ni thread-safe, ni nada de nada. Pero si nos cogemos el gran &lt;a href="http://www.amazon.com/CLR-via-Second-Pro-Developer/dp/0735621632"&gt;CLR via C#&lt;/a&gt; (libro totalmente recomendado) podemos entender como es que tan poco código hace tantas cosas. Toda la implementación gira en torno a los constructores estáticos y como funcionan dentro de .NET. Lo primero es entender que esto:&lt;/p&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;sealed&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;class&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Singleton&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;{&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; a = 5;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;}&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;En IL se traduce a esto:&lt;/p&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;sealed&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;class&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Singleton&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;{&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; a;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; Singleton()&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; a = 5;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;}&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Y que por ejemplo esto otro:&lt;/p&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;sealed&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;class&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Singleton&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;{ &lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; a = 5;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; b;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; Singleton() &lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; b = 10; &lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;}&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;En IL queda así:&lt;/p&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;sealed&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;class&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Singleton&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;{ &lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; a;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; b;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; Singleton() &lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; a = 5;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; b = 10; &lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;}&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Vamos, que las inicializaciones de variables estáticas una vez compilada la clase se incluyen dentro de un constructor estático (si el constructor existe se añaden al principio en el orden que son declaradas, si no existe se genera un constructor y se añaden).&lt;/p&gt;
&lt;p&gt;En C#, cuando el compilador JIT (el que pasa de IL a código máquina) encuentra un constructor estático, mira si ese constructor ya se ha ejecutado o no:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Si no se ha ejecutado, emite un lock, el código de ejecución y un unlock. &lt;/li&gt;
&lt;li&gt;Si se ha ejecutado, no emite nada. &lt;/li&gt;&lt;/ul&gt;
&lt;p&gt;Es decir, el JIT se asegura que el constructor estático solo se ejecute una vez aunque haya varios hilos, por eso en C# no hace falta poner el lock, ya que la línea &lt;em&gt;new Singleton()&lt;/em&gt; se ejecuta dentro del constructor estático y el propio JIT ya se ha encargado que ese constructor solo sea llamado una vez. Con esto ya tenemos cubierto el tema de thread-safe, pero ¿y lo de que sea lazy?&lt;/p&gt;
&lt;p&gt;Primero, tengo que reconocer que os he mentido un poco antes. Esta clase:&lt;/p&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;
&lt;p style="MARGIN:0px;"&gt;&lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;sealed&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;class&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Singleton&lt;/span&gt;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;{ &lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; a = 5;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;}&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;Y esta otra clase:&lt;/p&gt;
&lt;p&gt;&lt;span style="COLOR:blue;"&gt;public&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;sealed&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;class&lt;/span&gt; &lt;span style="COLOR:#2b91af;"&gt;Singleton&lt;/span&gt;&lt;/p&gt;
&lt;div style="FONT-FAMILY:consolas;BACKGROUND:white;COLOR:black;FONT-SIZE:10pt;"&gt;
&lt;p style="MARGIN:0px;"&gt;{ &lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; &lt;span style="COLOR:blue;"&gt;int&lt;/span&gt; a;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="COLOR:blue;"&gt;static&lt;/span&gt; Singleton() &lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; a = 5;&lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;/p&gt;
&lt;p style="MARGIN:0px;"&gt;}&lt;/p&gt;&lt;/div&gt;
&lt;p&gt;No generan exactamente el mismo IL: la primera está marcada con un atributo que se llama &lt;strong&gt;BeforeFieldInit&lt;/strong&gt; y la segunda no. Cuando una clase está marcada como &lt;strong&gt;BeforeFieldInit&lt;/strong&gt; el runtime del framework puede decidir ejecutar su inicializador de tipo (constructor estático) cuando se haga la primera referencia a ese tipo o antes, según le parezca. Pero si no está marcada con &lt;strong&gt;BeforeFieldInit&lt;/strong&gt; (porque hemos puesto un constructor estático explícito) entonces el inicializador del tipo solo puede ejecutarse en el momento que se haga uso de ese tipo.&lt;/p&gt;
&lt;p&gt;Es decir, como mi implementación del Singleton tiene un constructor estático, esta clase no está marcada como &lt;strong&gt;BeforeFieldInit&lt;/strong&gt; y lo que haya dentro del constructor estático (&lt;em&gt;new Singleton()&lt;/em&gt;) se ejecutará justo cuando haga &lt;em&gt;Singleton.Instance&lt;/em&gt;. Pero si no tuviera un constructor estático la línea &lt;em&gt;new Singleton()&lt;/em&gt; se podría ejecutar una hora antes de llamar a &lt;em&gt;Singleton.Instance&lt;/em&gt; (por ejemplo), según decida el runtime. Y esto puede ser un problema porque no tenemos ni idea de cuando se va a ejecutar ese constructor y si tiene código muy pesado puede ralentizar el resto del programa en algún punto que no sea adecuado, o incluso ejecutarse y que luego resulte que nunca se utiliza en el programa.&lt;/p&gt;
&lt;p&gt;Podéis encontrar una discusión mucho más en profundidad del tema en &lt;a href="http://www.yoda.arachsys.com/csharp/singleton.html"&gt;este&lt;/a&gt; artículo y &lt;a href="http://www.yoda.arachsys.com/csharp/beforefieldinit.html"&gt;este&lt;/a&gt; otro (cuentan lo mismo pero de forma mucho más técnica).&lt;/p&gt;
&lt;p&gt;Actualización: Reed Copsey ha publicado un artículo sobre este mismo tema llamado &lt;a href="http://reedcopsey.com/?p=39&amp;amp;cpage=1#comment-18"&gt;&amp;quot;Just keep repeating: C# is not Java. C# is not C++&amp;quot;&lt;/a&gt; que contiene más ejemplos y resulta bastante interesante.&lt;/p&gt;&lt;img src="http://kartones.net/aggbug.aspx?PostID=50052" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JadEngineBlog/~4/KOyWmLZC-Wc" height="1" width="1"/&gt;</description><category domain="http://kartones.net/blogs/jadengine/archive/tags/C_2300_/default.aspx">C#</category><feedburner:origLink>http://kartones.net/blogs/jadengine/archive/2009/05/20/el-patr-243-n-singleton-en-c.aspx</feedburner:origLink></item><item><title>Emprendedores</title><link>http://feeds.kartones.net/~r/JadEngineBlog/~3/I4XpRD8gUSE/emprendedores.aspx</link><pubDate>Wed, 08 Apr 2009 05:21:00 GMT</pubDate><guid isPermaLink="false">b86c0850-82e5-42ed-a9d8-bde9e8f94ec1:39208</guid><dc:creator>Vicente</dc:creator><slash:comments>7</slash:comments><comments>http://kartones.net/blogs/jadengine/archive/2009/04/08/emprendedores.aspx#comments</comments><description>&lt;p&gt;Hay un tipo de personas a las que &lt;strike&gt;envidio&lt;/strike&gt; admiro de sobremanera: los emprendedores. Yo siempre he tenido ideas que he pensado que podrían ser un buen producto, o al menos suficentemente decente para funcionar. Cuando empecé con esto de los videojuegos tenía la idea del juego definitivo, normalmente un refrito de los tres o cuatro juegos de moda del momento, y junto con algunos amigos y algún colaborador nos lanzábamos a lo loco a intentar realizarlos - seguro que al igual que muchos de los que leéis estas líneas.&lt;/p&gt;  &lt;p&gt;Todo empezaba genial, con la gente muy animada dedicando buena parte de su tiempo libre y de repente, un día:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Pepito ha ligado el finde anterior y ya no tiene tiempo para seguir en el proyecto.&lt;/li&gt;    &lt;li&gt;Juanito lleva 5 días sin dormir enganchado al Call of Duty 6. Pero es para intentar conseguir nuevas ideas, ya sabéis, hay que jugar a todas las obras maestras - aunque tu juego sea un clon del pong.&lt;/li&gt;    &lt;li&gt;Luisito está más pelao que las ratas y se ha buscado un trabajo, así que cuando termina su jornada solo le apetece tumbarse en el sofá y ver la tele.&lt;/li&gt;    &lt;li&gt;Jaimito viendo que los demás no hacen ni el huevo, obviamente se contagia del espíritu reinante y tampoco hace nada.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Total, que al cabo de dos meses el resultado es un proyecto cancelado y lo mismo hasta alguna bronca o discusión entre los integrantes del equipo. Después de un tiempo, y ya siendo más “maduros”, este proceso se vuelve a repetir con idénticos resultados y así N veces hasta que uno tras otro nos vamos dando cuenta que mejor dedicarnos a otra cosa.&lt;/p&gt;  &lt;p&gt;Pero hay gente que es capaz de salir de este círculo y llevar sus ideas adelante. Cuando te pones a analizarlo el resultado es sorprendente:&lt;/p&gt;  &lt;p align="center"&gt;¡han convertido su proyecto en su &lt;i&gt;trabajo&lt;/i&gt;!&lt;/p&gt;  &lt;p&gt;Traduciendo: de lunes a viernes dedican entre las 9 y las 19 a su idea (cuando las cosas van bien, cuando hay que apretar parecen un 7 Eleven). Y eso que también tienen novias y les encanta viciarse al Call of Duty 6. Además, ¡la de riesgos a los que se exponen frente a un trabajo tradicional! Que si no encuentras clientes, los proveedores te la lían, no consigues financiación,…&lt;/p&gt;  &lt;p&gt;Y esa es la forma de pensar que hace que uno no emprenda. O al menos es la que hace que yo no me atreva a emprender y admire a la gente que tiene los cojones de arriesgarse, y más en este país donde el fracaso está tan mal considerado – demasiado en mi opinión.&lt;/p&gt;  &lt;p&gt;Así que este post va dedicado a toda esa gente que da ese salto, que pone todo su esfuerzo en perseguir sus ideas, en confiar en ellas, y en no dejarse achantar por todos los posibles problemas que puedan cruzarse en su camino.&lt;/p&gt;  &lt;p&gt;Por suerte para mi, porque considero una fortuna poder hablar con este tipo de personas, conozco a bastante gente que ha emprendido y me gustaría dedicarles unas líneas:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;A &lt;a href="http://graphicdna.blogspot.com/"&gt;Iñaki Ayucar&lt;/a&gt; que posiblemente sea el tío que más sabe de gráficos y código manejado de España, y que lleva años apostando por su empresa &lt;a href="http://www.simaxvirt.com/"&gt;Simax&lt;/a&gt;, un simulador de conducción que es sencillamente impresionante.&lt;/li&gt;    &lt;li&gt;A mis compañeros de facultad que fundaron &lt;a href="http://vaelsys.com/"&gt;Vaelsys&lt;/a&gt;, una empresa especializada en visión artificial. Nunca se me olvidarán momentos como cuando Jorge hizo su parte de una práctica de Criptografía en Latín, o cuando Edu se vino a mi casa con su compañera a hacer prácticas de POO y el cabrón terminó comiendo palomitas mientras yo hacía el trabajo. Y encima al cabo de unas semanas vino quejándose de que solo había sacado un notable. Está claro que se le da bien ser jefe (y que yo soy un pringao).&lt;/li&gt;    &lt;li&gt;A la gente de &lt;a href="http://www.signumsoftware.com/"&gt;Signum Software&lt;/a&gt; y en particular a Olmo del Corral, que se han lanzado a la aventura de lanzar un &lt;a href="http://www.signumframework.com/"&gt;ORM&lt;/a&gt; open source en .NET con ideas bastante novedosas en algunos aspectos.&lt;/li&gt;    &lt;li&gt;A &lt;a href="http://www.cokidoo.com/"&gt;Cokidoo&lt;/a&gt;, empresa fundada por yens y Loover (entre otros), dos conocidos de &lt;a href="http://www.stratos-ad.com/"&gt;Stratos-AD&lt;/a&gt;. Están poniendo toda la carne en el asador con una &lt;a href="http://www.erasmusu.com/"&gt;red social&lt;/a&gt; enfocada a estudiantes de movilidad (erasmus,…) que tiene un acabado impecable. Ahora mismo están participando en el concurso BBVA Open Talent así que pasaros por &lt;a href="http://www.bbvaopentalent.com/erasmusu/"&gt;aquí&lt;/a&gt; y votadles.&lt;/li&gt;    &lt;li&gt;A &lt;a href="http://blep.blogspot.com/"&gt;ethernet&lt;/a&gt;, otro Stratero al que tuve la oportunidad de conocer en el Congreso de Desrrolladores de Videojuegos 08. Javi ha creado un producto llamado &lt;a href="http://www.agroguia.es/"&gt;Agroguía&lt;/a&gt; que es un sistema de guiado GPS para tractores. Un curioso nicho de mercado, todo sea dicho :p&lt;/li&gt;    &lt;li&gt;A SiPoX, un habitual de las Kdds madrileñas de Stratos-AD que ha fundado &lt;a href="http://www.undeadcode.com/"&gt;Undead Code&lt;/a&gt;, otra empresa orientada hacia el tema de aplicaciones web y web 2.0. También participan en el BBVA Open Talent con &lt;a href="http://www.somflee.com/"&gt;Somflee&lt;/a&gt;, una mezcla entre red social y herramienta de gestión de contenidos digitales. Podéis votarles &lt;a href="http://www.bbvaopentalent.com/somflee/"&gt;aquí&lt;/a&gt;.&lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Para todos ellos, lo mejor. A ver si un día de tanto hablar con vosotros se me contagia algo y me lanzo yo también a la aventura :) (¡acordaos de mi cuando seáis ricos!) &lt;/p&gt;&lt;img src="http://kartones.net/aggbug.aspx?PostID=39208" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JadEngineBlog/~4/I4XpRD8gUSE" height="1" width="1"/&gt;</description><category domain="http://kartones.net/blogs/jadengine/archive/tags/Off+Topic/default.aspx">Off Topic</category><feedburner:origLink>http://kartones.net/blogs/jadengine/archive/2009/04/08/emprendedores.aspx</feedburner:origLink></item><item><title>Árboles de Expresiones</title><link>http://feeds.kartones.net/~r/JadEngineBlog/~3/Q3qKZ9xTzrE/193-rboles-de-expresiones.aspx</link><pubDate>Tue, 31 Mar 2009 19:00:00 GMT</pubDate><guid isPermaLink="false">b86c0850-82e5-42ed-a9d8-bde9e8f94ec1:38764</guid><dc:creator>Vicente</dc:creator><slash:comments>0</slash:comments><comments>http://kartones.net/blogs/jadengine/archive/2009/03/31/193-rboles-de-expresiones.aspx#comments</comments><description>&lt;p&gt;Ahora que ya hemos visto que es una &lt;a href="http://kartones.net/blogs/jadengine/archive/2009/03/15/caracter-237-sticas-de-c-3-0-expresiones-lambda.aspx"&gt;expresión lambda&lt;/a&gt; podemos ver otra nueva característica mucho más “rara” de C# 3.0: los árboles de expresiones. En algunos lenguajes, como &lt;a href="http://en.wikipedia.org/wiki/Lisp_programming_language"&gt;Lisp&lt;/a&gt;, se permite manejar el código como si fueran datos y los datos como si fueran código (hace un par de días leyendo el blog del gran &lt;a href="http://blogs.msdn.com/ericlippert/"&gt;Eric Lippert&lt;/a&gt; descubrí que a esto se le llama &lt;i&gt;&lt;a href="http://blogs.msdn.com/ericlippert/archive/2009/03/23/five-dollar-words-for-programmers-part-three-homoiconic.aspx"&gt;homoiconic&lt;/a&gt;&lt;/i&gt;). Los árboles de expresión son la forma que tiene C# de implementar esta funcionalidad (de forma algo limitada).&lt;/p&gt;  &lt;p&gt;Por ejemplo, en el artículo anterior teníamos la expresión lambda:&lt;/p&gt;  &lt;div style="background:white none repeat scroll 0% 0%;font-family:consolas;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:black;font-size:10pt;"&gt;   &lt;p style="margin:0px;"&gt;num =&amp;gt; num &amp;lt; 5&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Que devolvía si un número era menor que cinco o no. Expresado en forma de un delegado del tipo Func, el código sería:&lt;/p&gt;  &lt;div style="background:white none repeat scroll 0% 0%;font-family:consolas;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:black;font-size:10pt;"&gt;   &lt;p style="margin:0px;"&gt;&lt;span&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;int&lt;/span&gt;, &lt;span style="color:blue;"&gt;bool&lt;/span&gt;&amp;gt; f = num =&amp;gt; num &amp;lt; 5;&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Y la forma de poner lo mismo usando un árbol de expresiones es:&lt;/p&gt;  &lt;div style="background:white none repeat scroll 0% 0%;font-family:consolas;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:black;font-size:10pt;"&gt;   &lt;p style="margin:0px;"&gt;System.Linq.Expressions.&lt;span&gt;Expression&lt;/span&gt;&amp;lt;&lt;span&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;int&lt;/span&gt;, &lt;span style="color:blue;"&gt;bool&lt;/span&gt;&amp;gt;&amp;gt; e = num =&amp;gt; num &amp;lt; 5;&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;La diferencia entre Func y Expression es que &lt;i&gt;&lt;b&gt;f&lt;/b&gt;&lt;/i&gt; es una función que se puede ejecutar:&lt;/p&gt;  &lt;div style="background:white none repeat scroll 0% 0%;font-family:consolas;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:black;font-size:10pt;"&gt;   &lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;bool&lt;/span&gt; result = f(10);&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Pero para ejecutar &lt;i&gt;&lt;b&gt;e&lt;/b&gt; &lt;/i&gt;tenemos que hacer lo siguiente:&lt;/p&gt;  &lt;div style="background:white none repeat scroll 0% 0%;font-family:consolas;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:black;font-size:10pt;"&gt;   &lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;bool&lt;/span&gt; result = e.Compile()(10);&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Es decir: para ejecutar un árbol de expresiones primero tenemos que compilarlo (porque son datos que representan código, no código en sí) y una vez compilado ya podemos utilizar el resultado como si fuera un método normal.&lt;/p&gt;  &lt;p&gt;De forma gráfica, &lt;i&gt;&lt;b&gt;e&lt;/b&gt;&lt;/i&gt; internamente está representado por el siguiente árbol:&lt;/p&gt;  &lt;p&gt;&lt;a href="http://kartones.net/blogs/jadengine/tree_0FED6B83.png"&gt;&lt;img src="http://kartones.net/blogs/jadengine/tree_thumb_48981590.png" style="border-width:0px;display:block;float:none;margin-left:auto;margin-right:auto;" title="tree" alt="tree" width="345" border="0" height="245" /&gt;&lt;/a&gt;Pero lo interesante de los árboles de expresiones es que en vez de dejar que el compilador los genere automáticamente, podemos construirlos nosotros a mano. Una vez tenemos una idea de como se representan internamente generarlos por código es bastante fácil (aunque algo tedioso):&lt;/p&gt;  &lt;div style="background:white none repeat scroll 0% 0%;font-family:consolas;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:black;font-size:10pt;"&gt;   &lt;pre style="margin:0px;"&gt;&lt;span&gt;ParameterExpression&lt;/span&gt; param = &lt;span&gt;Expression&lt;/span&gt;.Parameter(&lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(&lt;span style="color:blue;"&gt;int&lt;/span&gt;), &lt;span&gt;&amp;quot;num&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&lt;span&gt;ConstantExpression&lt;/span&gt; five = &lt;span&gt;Expression&lt;/span&gt;.Constant(5, &lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(&lt;span style="color:blue;"&gt;int&lt;/span&gt;));&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&lt;span&gt;BinaryExpression&lt;/span&gt; lessThan = &lt;span&gt;Expression&lt;/span&gt;.LessThan(param, five);&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&lt;span&gt;Expression&lt;/span&gt;&amp;lt;&lt;span&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;int&lt;/span&gt;, &lt;span style="color:blue;"&gt;bool&lt;/span&gt;&amp;gt;&amp;gt; e = &lt;span&gt;Expression&lt;/span&gt;.Lambda&amp;lt;&lt;span&gt;Func&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;int&lt;/span&gt;, &lt;span style="color:blue;"&gt;bool&lt;/span&gt;&amp;gt;&amp;gt; (lessThan, &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span&gt;ParameterExpression&lt;/span&gt;[] { param });&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Si hacemos un poco de memoria, en el mini motor de RPGs una parte bastante importante del código se encargaba de trabajar con las expresiones matemáticas que definen los valores de las variables de los objetos (los puntos de vida, el bonificador de ataque,…). Lo que hacíamos era definir el modificador en algún sitio (un fichero, una BD, …) como una expresión infijo, es decir, como esto:&lt;/p&gt;

&lt;div style="background:white none repeat scroll 0% 0%;font-family:consolas;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:black;font-size:10pt;" align="left"&gt;
  &lt;pre style="margin:0px;"&gt;(a) Attack = 3 * Level + 4 / 7 ^ 34 - 345&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Se aplicaba el algoritmo de &lt;a href="http://en.wikipedia.org/wiki/Shunting_yard_algorithm"&gt;Shunting-Yard&lt;/a&gt; para transformarla en una expresión postfijo:&lt;/p&gt;

&lt;div style="background:white none repeat scroll 0% 0%;font-family:consolas;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:black;font-size:10pt;" align="left"&gt;
  &lt;pre style="margin:0px;"&gt;(b) Attack = 3 Level * 4 7 34 ^ / + 345 -&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Y una vez teníamos (b) en forma postfijo se utilizaba un algoritmo para evaluar la expresión que lo que hace es construir un árbol con la siguiente pinta:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://kartones.net/blogs/jadengine/postfixeval_1CE74B94.png"&gt;&lt;img src="http://kartones.net/blogs/jadengine/postfixeval_thumb_27386FF4.png" style="border-width:0px;display:block;float:none;margin-left:auto;margin-right:auto;" title="postfixeval" alt="postfixeval" width="388" border="0" height="268" /&gt;&lt;/a&gt;Y sinceramente, este árbol se parece un montón al árbol del ejemplo anterior :) Así que el cambio realizado en la librería de RPGs va a utilizar árboles de expresiones para permitirnos pasar de esto:&lt;/p&gt;

&lt;div style="background:white none repeat scroll 0% 0%;font-family:consolas;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:black;font-size:10pt;" align="left"&gt;
  &lt;pre style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;string&lt;/span&gt; strExp = &lt;span&gt;&amp;quot;3 * Level + 4 / 7 ^ 34 - 345&amp;quot;&lt;/span&gt;;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;A esto:&lt;/p&gt;

&lt;div style="background:white none repeat scroll 0% 0%;font-family:consolas;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:black;font-size:10pt;"&gt;
  &lt;pre style="margin:0px;"&gt;&lt;span&gt;Func&lt;/span&gt;&amp;lt;&lt;span&gt;Evaluator&lt;/span&gt;, &lt;span style="color:blue;"&gt;double&lt;/span&gt;&amp;gt; func = (evaluator) =&amp;gt; 3 * evaluator.Chain(Level) + 4 / 7 ^ 34 - 345;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;¡Hemos transformado una cadena de texto en una función en C#! Esta función recibe un objeto del tipo Evaluator (que se utiliza para calcular el valor de las variables como Level, Dexterity,… de forma recursiva) y devuelve un double (el valor de la fórmula).&lt;/p&gt;

&lt;p&gt;El código que realiza esto es bastante sencillo (es una modificación del algoritmo de evaluación):&lt;/p&gt;

&lt;div style="background:white none repeat scroll 0% 0%;font-family:consolas;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:black;font-size:10pt;"&gt;
  &lt;pre style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; System;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; System.Collections.Generic;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; System.Linq;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; System.Text;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;using&lt;/span&gt; SLE = System.Linq.Expressions;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;namespace&lt;/span&gt; GravityAge.Rpg&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;{&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:blue;"&gt;class&lt;/span&gt; &lt;span&gt;Experiments&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #region&lt;/span&gt; Methods&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;public&lt;/span&gt; &lt;span style="color:blue;"&gt;static&lt;/span&gt; SLE.&lt;span&gt;Expression&lt;/span&gt;&amp;lt;&lt;span&gt;Func&lt;/span&gt;&amp;lt;&lt;span&gt;Evaluator&lt;/span&gt;, &lt;span style="color:blue;"&gt;double&lt;/span&gt;&amp;gt;&amp;gt; ToExpressionTree(&lt;span style="color:blue;"&gt;this&lt;/span&gt; &lt;span&gt;Expression&lt;/span&gt; expression)&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;Stack&lt;/span&gt;&amp;lt;SLE.&lt;span&gt;Expression&lt;/span&gt;&amp;gt; operands;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SLE.&lt;span&gt;Expression&lt;/span&gt; op1, op2;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; SLE.&lt;span&gt;ParameterExpression&lt;/span&gt; parameter = SLE.&lt;span&gt;Expression&lt;/span&gt;.Parameter(&lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(&lt;span&gt;Evaluator&lt;/span&gt;), &lt;span&gt;&amp;quot;evaluator&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; operands = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span&gt;Stack&lt;/span&gt;&amp;lt;SLE.&lt;span&gt;Expression&lt;/span&gt;&amp;gt;();&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;for&lt;/span&gt; (&lt;span style="color:blue;"&gt;int&lt;/span&gt; i = 0; i &amp;lt; expression.Terms.Count; i++)&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;switch&lt;/span&gt; (expression.Terms[i].TermType)&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;case&lt;/span&gt; &lt;span&gt;TermType&lt;/span&gt;.Number:&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; operands.Push(SLE.&lt;span&gt;Expression&lt;/span&gt;.Constant(expression.Terms[i].Value, &lt;span style="color:blue;"&gt;typeof&lt;/span&gt;(&lt;span style="color:blue;"&gt;double&lt;/span&gt;)));&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;break&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;case&lt;/span&gt; &lt;span&gt;TermType&lt;/span&gt;.Variable:&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; operands.Push(SLE.&lt;span&gt;Expression&lt;/span&gt;.Call(parameter, &lt;span&gt;&amp;quot;Chain&amp;quot;&lt;/span&gt;, &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span&gt;Type&lt;/span&gt;[] { }, SLE.&lt;span&gt;Expression&lt;/span&gt;.Constant(expression.Terms[i].Text)));&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;break&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;case&lt;/span&gt; &lt;span&gt;TermType&lt;/span&gt;.Operator:&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; op2 = operands.Pop();&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; op1 = operands.Pop();&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;switch&lt;/span&gt; (expression.Terms[i].TermOperator)&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;case&lt;/span&gt; &lt;span&gt;TermOperator&lt;/span&gt;.Add:&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; operands.Push(SLE.&lt;span&gt;Expression&lt;/span&gt;.Add(op1, op2));&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;break&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;case&lt;/span&gt; &lt;span&gt;TermOperator&lt;/span&gt;.Subtract:&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; operands.Push(SLE.&lt;span&gt;Expression&lt;/span&gt;.Subtract(op1, op2));&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;break&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;case&lt;/span&gt; &lt;span&gt;TermOperator&lt;/span&gt;.Multiply:&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; operands.Push(SLE.&lt;span&gt;Expression&lt;/span&gt;.Multiply(op1, op2));&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;break&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;case&lt;/span&gt; &lt;span&gt;TermOperator&lt;/span&gt;.Divide:&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; operands.Push(SLE.&lt;span&gt;Expression&lt;/span&gt;.Divide(op1, op2));&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;break&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;case&lt;/span&gt; &lt;span&gt;TermOperator&lt;/span&gt;.Power:&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; operands.Push(SLE.&lt;span&gt;Expression&lt;/span&gt;.Power(op1, op2));&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;break&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;break&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;default&lt;/span&gt;:&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;throw&lt;/span&gt; &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span&gt;ArgumentException&lt;/span&gt;(&lt;span&gt;&amp;quot;An undefined token (&amp;quot;&lt;/span&gt; + expression.Terms[i].Text + &lt;span&gt;&amp;quot;) appeared while calculating an expression.&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;if&lt;/span&gt; (operands.Count == 1)&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;return&lt;/span&gt; SLE.&lt;span&gt;Expression&lt;/span&gt;.Lambda&amp;lt;&lt;span&gt;Func&lt;/span&gt;&amp;lt;&lt;span&gt;Evaluator&lt;/span&gt;, &lt;span style="color:blue;"&gt;double&lt;/span&gt;&amp;gt;&amp;gt;(operands.Pop(), parameter);&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;else&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;return&lt;/span&gt; &lt;span style="color:blue;"&gt;null&lt;/span&gt;;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; #endregion&lt;/span&gt;&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/pre&gt;

  &lt;pre style="margin:0px;"&gt;}&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Como podréis ver el código se encuentra dentro de una clase llamada Experiments, ya que no tenía muy claro si iba a ser capaz de hacer esto o no cuando empecé :p Así que estos días me dedicaré a refactorizar y pulir algunas cosas y en breve subiré una nueva versión de la librería a Kartones por si a alguien le interesa.&lt;/p&gt;&lt;img src="http://kartones.net/aggbug.aspx?PostID=38764" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JadEngineBlog/~4/Q3qKZ9xTzrE" height="1" width="1"/&gt;</description><category domain="http://kartones.net/blogs/jadengine/archive/tags/Statecraft/default.aspx">Statecraft</category><category domain="http://kartones.net/blogs/jadengine/archive/tags/RPG/default.aspx">RPG</category><category domain="http://kartones.net/blogs/jadengine/archive/tags/C_2300_/default.aspx">C#</category><feedburner:origLink>http://kartones.net/blogs/jadengine/archive/2009/03/31/193-rboles-de-expresiones.aspx</feedburner:origLink></item><item><title>Características de C# 3.0 – Expresiones Lambda</title><link>http://feeds.kartones.net/~r/JadEngineBlog/~3/J6S6DGP-V90/caracter-237-sticas-de-c-3-0-expresiones-lambda.aspx</link><pubDate>Sun, 15 Mar 2009 01:06:00 GMT</pubDate><guid isPermaLink="false">b86c0850-82e5-42ed-a9d8-bde9e8f94ec1:38027</guid><dc:creator>Vicente</dc:creator><slash:comments>3</slash:comments><comments>http://kartones.net/blogs/jadengine/archive/2009/03/15/caracter-237-sticas-de-c-3-0-expresiones-lambda.aspx#comments</comments><description>&lt;p&gt;En el artículo &lt;a href="http://kartones.net/blogs/jadengine/archive/2009/02/09/implementando-el-reglamendo-de-un-rpg.aspx"&gt;anterior&lt;/a&gt; comenté el diseño de una pequeña librería para implementar las reglas de un RPG. Desde ese día he realizado pequeños cambios en el código con el objetivo de simplificarlo y aumentar el rendimiento. En este artículo (y el próximo) voy a hablar de algunas características nuevas de C# 3.0 que permiten que nuestra librería sea mucho más flexible.&lt;/p&gt;  &lt;p&gt;En C# 3.0 la gente de Microsoft añadió muchas mejoras en el lenguaje, la mayoría inspirada en los lenguajes funcionales como &lt;a href="http://en.wikipedia.org/wiki/Lisp_programming_language"&gt;Lisp&lt;/a&gt;, &lt;a href="http://en.wikipedia.org/wiki/Ocaml"&gt;OCaml&lt;/a&gt;,… En particular hay dos que van de la mano: las &lt;a href="http://msdn.microsoft.com/en-us/library/bb397687.aspx"&gt;expresiones lambda&lt;/a&gt; y los &lt;a href="http://msdn.microsoft.com/en-us/library/bb397951.aspx"&gt;árboles de expresiones&lt;/a&gt;. Este primer artículo va a tratar de las expresiones lambda, así que recordemos que era un delegado y poco a poco veremos el porqué se añadieron todas estas nuevas características a C#.&lt;/p&gt;  &lt;p&gt;Por ejemplo, queremos filtrar una lista de elementos T en base a un criterio pero queremos que el criterio sea modificable. Este “criterio” es una función que recibirá un T y devolverá un booleano indicando si el elemento cumple el criterio o no. En código tradicional de C# esto sería un delegado y sería algo como lo que sigue:&lt;/p&gt;  &lt;div style="background:white none repeat scroll 0% 0%;font-family:consolas;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:black;font-size:10pt;"&gt;   &lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;delegate&lt;/span&gt; &lt;span style="color:blue;"&gt;bool&lt;/span&gt; &lt;span&gt;Criteria&lt;/span&gt;&amp;lt;T&amp;gt;(T element);&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;class&lt;/span&gt; &lt;span&gt;Program&lt;/span&gt;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;{&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span&gt;List&lt;/span&gt;&amp;lt;T&amp;gt; FilterList&amp;lt;T&amp;gt;(&lt;span&gt;List&lt;/span&gt;&amp;lt;T&amp;gt; list, &lt;span&gt;Criteria&lt;/span&gt;&amp;lt;T&amp;gt; criteria)&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;List&lt;/span&gt;&amp;lt;T&amp;gt; newList = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span&gt;List&lt;/span&gt;&amp;lt;T&amp;gt;();&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;foreach&lt;/span&gt; (T element &lt;span style="color:blue;"&gt;in&lt;/span&gt; list)&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;if&lt;/span&gt; (criteria(element))&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; newList.Add(element);&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;return&lt;/span&gt; newList;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:blue;"&gt;bool&lt;/span&gt; CriteriaLessThan5(&lt;span style="color:blue;"&gt;int&lt;/span&gt; intValue)&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;return&lt;/span&gt; intValue &amp;lt; 5;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:blue;"&gt;bool&lt;/span&gt; CriteriaBiggerThan5(&lt;span style="color:blue;"&gt;int&lt;/span&gt; intValue)&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;return&lt;/span&gt; intValue &amp;gt; 5;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:blue;"&gt;void&lt;/span&gt; Main(&lt;span style="color:blue;"&gt;string&lt;/span&gt;[] args)&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;int&lt;/span&gt;&amp;gt; numbers = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;int&lt;/span&gt;&amp;gt;() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;int&lt;/span&gt;&amp;gt; numbers2;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; numbers2 = FilterList(numbers, CriteriaLessThan5);&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;foreach&lt;/span&gt; (&lt;span style="color:blue;"&gt;int&lt;/span&gt; number &lt;span style="color:blue;"&gt;in&lt;/span&gt; numbers2)&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;Console&lt;/span&gt;.WriteLine(number);&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; numbers2 = FilterList(numbers, CriteriaBiggerThan5);&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;foreach&lt;/span&gt; (&lt;span style="color:blue;"&gt;int&lt;/span&gt; number &lt;span style="color:blue;"&gt;in&lt;/span&gt; numbers2)&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;Console&lt;/span&gt;.WriteLine(number);&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;Console&lt;/span&gt;.ReadKey();&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;    &lt;p style="margin:0px;"&gt;}&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Si os fijáis he declarado un delegado (Criteria) que recibe un elemento T y devuelve bool. Luego he añadido una función FilterList que recibe una lista y un criterio y devuelve la lista filtrada y por último en el main he usado dos funciones diferentes para filtrar una misma lista de números.&lt;/p&gt;  &lt;p&gt;A partir de C# 2.0 se añadió al lenguaje la capacidad de declarar delegados anónimos (al vuelo). Usando delegados anónimos el código anterior tendría la siguiente pinta:&lt;/p&gt;  &lt;div style="background:white none repeat scroll 0% 0%;font-family:consolas;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:black;font-size:10pt;"&gt;   &lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;delegate&lt;/span&gt; &lt;span style="color:blue;"&gt;bool&lt;/span&gt; &lt;span&gt;Criteria&lt;/span&gt;&amp;lt;T&amp;gt;(T element);&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;class&lt;/span&gt; &lt;span&gt;Program2&lt;/span&gt;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;{&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span&gt;List&lt;/span&gt;&amp;lt;T&amp;gt; FilterList&amp;lt;T&amp;gt;(&lt;span&gt;List&lt;/span&gt;&amp;lt;T&amp;gt; list, &lt;span&gt;Criteria&lt;/span&gt;&amp;lt;T&amp;gt; criteria)&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;List&lt;/span&gt;&amp;lt;T&amp;gt; newList = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span&gt;List&lt;/span&gt;&amp;lt;T&amp;gt;();&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;foreach&lt;/span&gt; (T element &lt;span style="color:blue;"&gt;in&lt;/span&gt; list)&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;if&lt;/span&gt; (criteria(element))&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; newList.Add(element);&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;return&lt;/span&gt; newList;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:blue;"&gt;void&lt;/span&gt; Main(&lt;span style="color:blue;"&gt;string&lt;/span&gt;[] args)&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;int&lt;/span&gt;&amp;gt; numbers = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;int&lt;/span&gt;&amp;gt;() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;int&lt;/span&gt;&amp;gt; numbers2;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; numbers2 = FilterList(numbers, &lt;span style="color:blue;"&gt;delegate&lt;/span&gt;(&lt;span style="color:blue;"&gt;int&lt;/span&gt; e) { &lt;span style="color:blue;"&gt;return&lt;/span&gt; e &amp;lt; 5; });&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;foreach&lt;/span&gt; (&lt;span style="color:blue;"&gt;int&lt;/span&gt; number &lt;span style="color:blue;"&gt;in&lt;/span&gt; numbers2)&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;Console&lt;/span&gt;.WriteLine(number);&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; numbers2 = FilterList(numbers, &lt;span style="color:blue;"&gt;delegate&lt;/span&gt;(&lt;span style="color:blue;"&gt;int&lt;/span&gt; e) { &lt;span style="color:blue;"&gt;return&lt;/span&gt; e &amp;gt; 5; });&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;foreach&lt;/span&gt; (&lt;span style="color:blue;"&gt;int&lt;/span&gt; number &lt;span style="color:blue;"&gt;in&lt;/span&gt; numbers2)&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;Console&lt;/span&gt;.WriteLine(number);&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;Console&lt;/span&gt;.ReadKey();&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;    &lt;p style="margin:0px;"&gt;}&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Ahora los delegados están metidos directamente en la llamada al método FilterList. En C# 3.0 se añaden las expresiones lambda que es una forma más “bonita” de escribir lo mismo. Además se añaden los delegados genéricos &lt;a href="http://msdn.microsoft.com/en-us/library/018hxwa8.aspx"&gt;Action&lt;/a&gt; y &lt;a href="http://msdn.microsoft.com/en-us/library/bb534960.aspx"&gt;Func&lt;/a&gt; que nos ahorran tener que declarar delegados propios. Con lo que en C# 3.0 nuestro código quedaría así:&lt;/p&gt;  &lt;div style="background:white none repeat scroll 0% 0%;font-family:consolas;-moz-background-clip:-moz-initial;-moz-background-origin:-moz-initial;-moz-background-inline-policy:-moz-initial;color:black;font-size:10pt;"&gt;   &lt;p style="margin:0px;"&gt;&lt;span style="color:blue;"&gt;class&lt;/span&gt; &lt;span&gt;Program3&lt;/span&gt;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;{&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span&gt;List&lt;/span&gt;&amp;lt;T&amp;gt; FilterList&amp;lt;T&amp;gt;(&lt;span&gt;List&lt;/span&gt;&amp;lt;T&amp;gt; list, &lt;span&gt;Func&lt;/span&gt;&amp;lt;T, &lt;span style="color:blue;"&gt;bool&lt;/span&gt;&amp;gt; criteria)&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;List&lt;/span&gt;&amp;lt;T&amp;gt; newList = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span&gt;List&lt;/span&gt;&amp;lt;T&amp;gt;();&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;foreach&lt;/span&gt; (T element &lt;span style="color:blue;"&gt;in&lt;/span&gt; list)&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;if&lt;/span&gt; (criteria(element))&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; newList.Add(element);&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;return&lt;/span&gt; newList;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;static&lt;/span&gt; &lt;span style="color:blue;"&gt;void&lt;/span&gt; Main(&lt;span style="color:blue;"&gt;string&lt;/span&gt;[] args)&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;int&lt;/span&gt;&amp;gt; numbers = &lt;span style="color:blue;"&gt;new&lt;/span&gt; &lt;span&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;int&lt;/span&gt;&amp;gt;() { 1, 2, 3, 4, 5, 6, 7, 8, 9 };&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;List&lt;/span&gt;&amp;lt;&lt;span style="color:blue;"&gt;int&lt;/span&gt;&amp;gt; numbers2;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; numbers2 = FilterList(numbers, e =&amp;gt; e &amp;lt; 5);&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;foreach&lt;/span&gt; (&lt;span style="color:blue;"&gt;int&lt;/span&gt; number &lt;span style="color:blue;"&gt;in&lt;/span&gt; numbers2)&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;Console&lt;/span&gt;.WriteLine(number);&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; numbers2 = FilterList(numbers, e =&amp;gt; e &amp;gt; 5);&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span style="color:blue;"&gt;foreach&lt;/span&gt; (&lt;span style="color:blue;"&gt;int&lt;/span&gt; number &lt;span style="color:blue;"&gt;in&lt;/span&gt; numbers2)&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;Console&lt;/span&gt;.WriteLine(number);&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;span&gt;Console&lt;/span&gt;.ReadKey();&lt;/p&gt;    &lt;p style="margin:0px;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/p&gt;    &lt;p style="margin:0px;"&gt;}&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;Fijaos cómo ahora ya no se declara ningún delegado “Criteria” porque FilterList recibe un Func&amp;lt;T, bool&amp;gt;, es decir, un delegado genérico que tiene un parámetro T y devuelve un bool. Y además hemos sustituido en la llamada a FilterList lo de “delegate(int e)…” por una expresión lambda (=&amp;gt;) que recibe un “e” y devuelve si ese “e” es menor o mayor que 5 (el compilador automáticamente infiere que “e” tiene que ser de tipo int).&lt;/p&gt;  &lt;p&gt;En el próximo artículo veremos como se relacionan las expresiones lambda con los árboles de expresiones, que nos permiten generar y modificar código de forma dinámica dentro del propio programa (código como datos, algo bastante común en los lenguajes funcionales) y la utilidad que tiene esto en una librería para implementar RPGs.&lt;/p&gt;&lt;img src="http://kartones.net/aggbug.aspx?PostID=38027" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JadEngineBlog/~4/J6S6DGP-V90" height="1" width="1"/&gt;</description><category domain="http://kartones.net/blogs/jadengine/archive/tags/Statecraft/default.aspx">Statecraft</category><category domain="http://kartones.net/blogs/jadengine/archive/tags/RPG/default.aspx">RPG</category><category domain="http://kartones.net/blogs/jadengine/archive/tags/C_2300_/default.aspx">C#</category><feedburner:origLink>http://kartones.net/blogs/jadengine/archive/2009/03/15/caracter-237-sticas-de-c-3-0-expresiones-lambda.aspx</feedburner:origLink></item><item><title>Implementando el reglamento de un RPG</title><link>http://feeds.kartones.net/~r/JadEngineBlog/~3/O9uug9nrBt8/implementando-el-reglamendo-de-un-rpg.aspx</link><pubDate>Mon, 09 Feb 2009 07:52:00 GMT</pubDate><guid isPermaLink="false">b86c0850-82e5-42ed-a9d8-bde9e8f94ec1:37099</guid><dc:creator>Vicente</dc:creator><slash:comments>5</slash:comments><comments>http://kartones.net/blogs/jadengine/archive/2009/02/09/implementando-el-reglamendo-de-un-rpg.aspx#comments</comments><description>&lt;p&gt;&lt;b&gt;Aviso:&lt;/b&gt; este artículo es bastante largo, aunque no demasiado técnico, así que debería ser fácil de seguir.&lt;/p&gt;  &lt;p&gt;Desde hace bastantes años siempre he tenido la idea de portar las reglas del &lt;a href="http://en.wikipedia.org/wiki/Dungeons_&amp;amp;_Dragons"&gt;Dungeons and Dragons&lt;/a&gt; (o algo similar) al ordenador, pero siempre he terminado fracasando por varios motivos:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Son sistemas muy complicados. &lt;/li&gt;    &lt;li&gt;Están llenos de excepciones. &lt;/li&gt;    &lt;li&gt;Tienen que ser muy extensibles porque seguramente aparecerán nuevas reglas con el paso del tiempo. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Estos días he tenido bastante tiempo libre y he decido intentar por n-esima vez hacer un “mini-framework” que me permita implementar algo parecido a una simplificacón del &lt;a href="http://en.wikipedia.org/wiki/D20_System"&gt;sistema d20&lt;/a&gt; para mis propios proyectos. El resto de este artículo va a tratar de los problemas que he encontrado para realizar esta implementación básica (aún le faltan muchas cosas). Al final de todo hay un link con el código fuente para él que le quiera echar un vistazo.&lt;/p&gt;  &lt;p&gt;El primer problema que me he encontrado siempre al intentar hacer este tipo de sistemas es que los objetos tienen muchísimas propiedades. Por ejemplo un personaje tiene atributos, habilidades, dotes, conjuros, equipo, clases,… A pesar de agrupar en clases y usar todas las herramientas que proporciona la programación orientada a objetos siempre he terminado teniendo en cada clase un ejército de propiedades que se vuelve inmanejable.&lt;/p&gt;  &lt;p&gt;Así que decidí atacar el problema de otra forma: cada clase tiene una tabla hash que representa sus propiedades. De esta forma cada clase puede tener “infinitas” propiedades y además las puedo definir cuando quiera. Si quiero una propiedad hago:&lt;/p&gt;  &lt;pre&gt;&lt;pre style="margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;font-size:12px;"&gt;objeto.Set(&amp;quot;&lt;span&gt;Propiedad&lt;/span&gt;&amp;quot;, valor);&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Y si quiero obtener el valor hago:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;font-size:12px;"&gt;&lt;span&gt;object&lt;/span&gt; resultado = objeto.Get(&amp;quot;&lt;span&gt;Propiedad&lt;/span&gt;&amp;quot;);&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;La verdad que casi cualquiera que vea esto pensará que esta aproximación tiene muchos problemas:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Se usan strings para los nombres de las propiedades y es muy fácil equivocarse al escribirlos (confundir una mayúscula, una letra,…) y que el programa de un error o devuelva un valor erróneo. Depurar esto es un jaleo bastante serio. &lt;/li&gt;

  &lt;li&gt;Hay que calcular hashes de strings todo el rato (una operación bastante lenta). &lt;/li&gt;

  &lt;li&gt;No es tipada: tenemos objects por todos los lados que tenemos que castear al tipo correcto (lento y propenso a errores). &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;La verdad que yo mismo no estaba muy convencido de que esto fuera una buena idea hasta que me encontré &lt;a href="http://steve-yegge.blogspot.com/2008/10/universal-design-pattern.html"&gt;este&lt;/a&gt; artículo de Steve Yegge donde habla del patrón &lt;a href="http://en.wikipedia.org/wiki/Prototype_pattern"&gt;prototype&lt;/a&gt; y de la programación basada en prototipos en vez de orientada a objetos.&lt;/p&gt;

&lt;p&gt;El artículo, aún siendo largo, es bastante interesante y explica bastante bien que es y como se usan los prototipos. Resumiendo mucho: un prototipo es una tabla hash que contiene todas las propiedades y operaciones de un objeto (en vez de ser entidades independientes como en la programación orientada a objetos).&lt;/p&gt;

&lt;p&gt;Dado que yo programo en C# y que este lenguaje no da soporte para prototipos (como por ejemplo &lt;a href="http://en.wikipedia.org/wiki/Io_%28programming_language%29"&gt;IO&lt;/a&gt;), implementé las ideas del post de Steve en la clase &lt;b&gt;Prototype&lt;/b&gt;. Esta clase contiene:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Un campo &lt;i&gt;parent&lt;/i&gt; que es el prototipo del que se “hereda”. &lt;/li&gt;

  &lt;li&gt;Un campo &lt;i&gt;properties&lt;/i&gt; que es el diccionario de propiedades. &lt;/li&gt;

  &lt;li&gt;Una propiedad &lt;i&gt;IsReadOnly&lt;/i&gt; que permite hacer al prototipo de solo lectura. &lt;/li&gt;

  &lt;li&gt;Cuatro métodos (&lt;i&gt;Get&lt;/i&gt;, &lt;i&gt;Set&lt;/i&gt;, &lt;i&gt;Contains&lt;/i&gt; y &lt;i&gt;Remove&lt;/i&gt;) que permiten modificar la información del prototipo. &lt;/li&gt;

  &lt;li&gt;Y un método &lt;i&gt;Clone&lt;/i&gt; que permite crear un nuevo prototipo que herede del actual. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lo único interesante de esta clase es que los métodos &lt;i&gt;Get&lt;/i&gt; y &lt;i&gt;Contains&lt;/i&gt; permiten buscar valores en el padre del prototipo. Es decir, &lt;i&gt;parent&lt;/i&gt; cumple la función de la superclase en la programación orientada a objetos. Como podéis ver, esta implementación no es nada complicada y permite hacer cosas como:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;font-size:12px;"&gt;Prototype guardia = &lt;span&gt;new&lt;/span&gt; Prototype();&lt;br /&gt;&lt;/pre&gt;&lt;pre style="margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;font-size:12px;"&gt;guardia.Set(&amp;quot;&lt;span&gt;Ataque&lt;/span&gt;&amp;quot;, 10);&lt;br /&gt;&lt;/pre&gt;&lt;pre style="margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;font-size:12px;"&gt;guardia.Set(&amp;quot;&lt;span&gt;Vida&lt;/span&gt;&amp;quot;, 5);&lt;br /&gt;&lt;/pre&gt;&lt;pre style="margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;font-size:12px;"&gt;&lt;/pre&gt;&lt;pre style="margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;font-size:12px;"&gt;Prototype alitar = guardia.Clone();&lt;br /&gt;&lt;/pre&gt;&lt;pre style="margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;font-size:12px;"&gt;alitar.Set(&amp;quot;&lt;span&gt;Nombre&lt;/span&gt;&amp;quot;, &amp;quot;&lt;span&gt;Alitar&lt;/span&gt;&amp;quot;);&lt;br /&gt;&lt;/pre&gt;&lt;pre style="margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;font-size:12px;"&gt;alitar.Set(&amp;quot;&lt;span&gt;TieneMiedoALosDragones&lt;/span&gt;&amp;quot;, &lt;span&gt;true&lt;/span&gt;);&lt;br /&gt;&lt;/pre&gt;&lt;/pre&gt;

&lt;p&gt;Como se puede ver, he definido un guardia prototipo y luego un guardia especial que he llamado Alitar y que tiene miedo a los dragones. Alitar se comportará como cualquier otro guardia, pero cuando vea un dragón huirá en vez de luchar (¿quizás también tendría que ponerle más inteligencia? :p).&lt;/p&gt;

&lt;p&gt;Una vez resuelto el problema fácil, queda el difícil (y bastante más interesante): calcular lo que vale una variable en un RPG. Por ejemplo: ¿cuanto vale el bonificador de ataque cuerpo a cuerpo de un personaje? En el d20 este número depende de muchísimas cosas:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;La fuerza del personaje (o la destreza según que arma esté usando y si tiene las dotes adecuadas). &lt;/li&gt;

  &lt;li&gt;El nivel de cada clase del personaje. &lt;/li&gt;

  &lt;li&gt;Sus dotes. &lt;/li&gt;

  &lt;li&gt;Conjuros. &lt;/li&gt;

  &lt;li&gt;Otras habilidades o modificadores circunstanciales. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Básicamente calcular ciertos valores en un RPG es un lío increíble. Hace tiempo descubrí una herramienta llamada &lt;a href="http://pcgen.sourceforge.net/"&gt;PCGen&lt;/a&gt; que es un generador de personajes para el sistema d20. Esta herramienta tiene un lenguaje de definición de reglas muy potente, por ejemplo:&lt;/p&gt;

&lt;p align="center"&gt;&lt;b&gt;&lt;i&gt;BONUS:COMBAT|AC|Level / 2|TYPE=NaturalArmor.REPLACE&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;

&lt;p align="left"&gt;Esta línea significa un bonificador de combate a la armadura (AC) igual al nivel del personaje dividido entre dos, del tipo armadura natural que reemplaza a cualquier bonificador existente del mismo tipo. Este ejemplo es bastante básico, pero hay verdaderas virguerías definidas con él.&lt;/p&gt;

&lt;p align="left"&gt;Así que realmente el segundo problema son dos subproblemas:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;div align="left"&gt;Como definir modificadores y expresiones matemáticas (Level / 2).&lt;/div&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;div align="left"&gt;Como saber que modificadores afectan a una variable y como evaluar el valor de la misma.&lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p align="left"&gt;El primer subproblema es “sencillo” de resolver si uno no se complica mucho la vida. En mi caso decidí imponer a las expresiones la restricción de que las diferentes partes que la forman deberían estar separadas por un espacio. Esto me permite partir la expresión con una sola llamada a &lt;a href="http://msdn.microsoft.com/en-us/library/system.string.split.aspx"&gt;String.Split&lt;/a&gt;. Luego un simple parser recorre los pedazos de la expresión y los clasifica en cuatro tipos:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;div align="left"&gt;&lt;b&gt;Números:&lt;/b&gt; 3, 5.7, 23434,…&lt;/div&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;div align="left"&gt;&lt;b&gt;Operadores:&lt;/b&gt; +, –, *, /, ^&lt;/div&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;div align="left"&gt;&lt;b&gt;Símbolos:&lt;/b&gt; (, )&lt;/div&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;div align="left"&gt;&lt;b&gt;Variables:&lt;/b&gt; cualquier otra cosa&lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p align="left"&gt;Esto debería ser suficiente para definir cualquier tipo de operación matemática que pueda ser de utilidad. En el fichero &lt;b&gt;ExpressionParser.cs&lt;/b&gt; se puede ver el código de este pequeño parser. Una cosa “curiosa” del código es que al final del parseo se ejecuta una función llamada &lt;i&gt;ShuntingYard&lt;/i&gt;. Esta función implementa el algoritmo de &lt;a href="http://en.wikipedia.org/wiki/Shunting_yard_algorithm"&gt;Shunting-Yard&lt;/a&gt; inventado por &lt;a href="http://en.wikipedia.org/wiki/Edsger_W._Dijkstra"&gt;Djikstra&lt;/a&gt; que permite pasar expresiones en formato &lt;a href="http://en.wikipedia.org/wiki/Infix_notation"&gt;infijo&lt;/a&gt; (2 + 3) a formato &lt;a href="http://en.wikipedia.org/wiki/Postfix_notation"&gt;postfijo&lt;/a&gt; o notación polaca inversa (2 3 +).&lt;/p&gt;

&lt;p align="left"&gt;¿Y por qué hacer semejante cosa? Porque la notación postfijo tiene una gran ventaja: es muy fácil de evaluar. Estoy seguro que hacerse un evaluador de expresiones en formato infijo no es demasiado difícil, pero en formato postfijo es trivial y el coste de transformar la expresión es muy bajo (y solo hay que pagarlo una vez).&lt;/p&gt;

&lt;p align="left"&gt;Y por último hay que ver como buscar los modificadores que afectan a una variable y como calcular su valor. Imaginemos que tenemos un objeto Espada definido de esta forma:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;font-size:12px;"&gt;Prototype arma = &lt;span&gt;new&lt;/span&gt; Prototype();&lt;br /&gt;&lt;/pre&gt;&lt;pre style="margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;font-size:12px;"&gt;arma.Set(&amp;quot;&lt;span&gt;Nombre&lt;/span&gt;&amp;quot;, &amp;quot;&lt;span&gt;Espada&lt;/span&gt;&amp;quot;);&lt;br /&gt;&lt;/pre&gt;&lt;pre style="margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;font-size:12px;"&gt;arma.Set(&amp;quot;&lt;span&gt;Dureza&lt;/span&gt;&amp;quot;, 5);&lt;/pre&gt;&lt;/pre&gt;

&lt;p align="left"&gt;Para obtener su dureza basta con escribir:&lt;/p&gt;

&lt;pre&gt;&lt;pre style="margin:0em;width:100%;font-family:consolas,&amp;#39;Courier New&amp;#39;,courier,monospace;font-size:12px;"&gt;&lt;span&gt;int&lt;/span&gt; dureza = arma.Get&amp;lt;&lt;span&gt;int&lt;/span&gt;&amp;gt;(&amp;quot;&lt;span&gt;Dureza&lt;/span&gt;&amp;quot;);&lt;/pre&gt;&lt;/pre&gt;

&lt;p align="left"&gt;Ahora imaginemos que cojo a la Espada y la modifico añadiéndole otro prototypo que representa que está hecha de Mithril, lo que le da una dureza extra.&lt;/p&gt;

&lt;p align="left"&gt;&lt;a href="http://kartones.net/blogs/jadengine/imagen1_4ADEE8EE.png"&gt;&lt;img src="http://kartones.net/blogs/jadengine/imagen1_thumb_33637316.png" style="border-width:0px;display:block;float:none;margin-left:auto;margin-right:auto;" title="imagen1" alt="imagen1" width="131" border="0" height="156" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p align="left"&gt;Para calcular su dureza ahora hay que buscar en sus modificadores pero también en los del objeto Mithril. En el siguiente diagrama se puede ver un ejemplo un poco más complicado:&lt;/p&gt;

&lt;p align="left"&gt;&lt;a href="http://kartones.net/blogs/jadengine/imagen2_12DC3364.png"&gt;&lt;img src="http://kartones.net/blogs/jadengine/imagen2_thumb_5D63713E.png" style="border-width:0px;display:block;float:none;margin-left:auto;margin-right:auto;" title="imagen2" alt="imagen2" width="281" border="0" height="246" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p align="left"&gt;Se puede ver que se ha formado una estructura en forma de árbol, así que para buscar los modificadores decidí utilizar una &lt;a href="http://en.wikipedia.org/wiki/Breadth-first_search"&gt;búsqueda en anchura&lt;/a&gt;: primero la raiz, luego los hijos, luego los hijos de los hijos,…&lt;/p&gt;

&lt;p align="left"&gt;Pero ahora imaginemos que esa espada está en manos de un personaje que es de la clase bárbaro, y que los bárbaros hacen que todos los objetos en sus manos sean menos duros (porque tienden a romperlos).&lt;/p&gt;

&lt;p align="left"&gt;&lt;a href="http://kartones.net/blogs/jadengine/imagen3_3CDC318C.png"&gt;&lt;img src="http://kartones.net/blogs/jadengine/imagen3_thumb_3C6FFE97.png" style="border-width:0px;display:block;float:none;margin-left:auto;margin-right:auto;" title="imagen3" alt="imagen3" width="329" border="0" height="310" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p align="left"&gt;Como se puede ver la dureza del arma ha sido modificada por un valor que no está en sus hijos, si no que está en otra parte del árbol. Así que hay que modificar un poco la búsqueda en anchura:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;div align="left"&gt;Se busca la verdadera raíz del árbol a partir del nodo al que se le pidió el valor.&lt;/div&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;div align="left"&gt;Se inicia la búsqueda en anchura desde este nodo.&lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p align="left"&gt;Pero sigamos imaginando: ahora el personaje también tiene una Armadura y esta a su vez es de Adamantio.&lt;/p&gt;

&lt;p align="left"&gt;&lt;a href="http://kartones.net/blogs/jadengine/imagen4_50F54E15.png"&gt;&lt;img src="http://kartones.net/blogs/jadengine/imagen4_thumb_29BB04E0.png" style="border-width:0px;display:block;float:none;margin-left:auto;margin-right:auto;" title="imagen4" alt="imagen4" width="441" border="0" height="291" /&gt;&lt;/a&gt;Está claro que si pregunto por la dureza de la Espada no debería influir para nada los modificadores a la dureza de la Armadura o del Adamantio. Para resolver este nuevo problema hay que añadir una nueva propiedad a los modificadores: visibilidad (global o local). Y hay que volver a cambiar la búsqueda en anchura:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;div align="left"&gt;Se guarda el nodo que inició la búsqueda (la Espada).&lt;/div&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;div align="left"&gt;Se comienza la búsqueda desde la raíz (el Personaje).&lt;/div&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;div align="left"&gt;Si el modificador está en un nodo fuera del subárbol definido por el nodo que inició la búsqueda, solo se aplicarán los modificadores globales. Si el modificador está definido en un nodo perteneciente al subárbol se aplicarán todos los tipos de modificadores.&lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p align="left"&gt;&lt;a href="http://kartones.net/blogs/jadengine/imagen5_6984EB65.png"&gt;&lt;img src="http://kartones.net/blogs/jadengine/imagen5_thumb_372117E6.png" style="border-width:0px;display:block;float:none;margin-left:auto;margin-right:auto;" title="imagen5" alt="imagen5" width="469" border="0" height="312" /&gt;&lt;/a&gt;La búsqueda se inició en el objeto Espada, así que fuera del subárbol que define (marcado en rojo) solo se aplican los modificadores marcados como global. Así conseguimos que se aplique el modificador de Bárbaro pero no el de Armadura o Adamantio.&lt;/p&gt;

&lt;p align="left"&gt;Esta forma de buscar modificadores cubre todos los casos que se me han ocurrido. Seguro que hay situaciones que no resuelvo, pero no me pienso complicar más la vida (de momento y sin una buena razón). &lt;/p&gt;

&lt;p align="left"&gt;Ya está la búsqueda de modificadores, ahora queda ver como calcular el valor de una variable. El valor de una variable es modificado por los objetos de tipo &lt;b&gt;Modifier&lt;/b&gt; que a su vez contienen expresiones matemáticas en forma de objetos &lt;b&gt;Expression&lt;/b&gt;. Estas expresiones pueden ser simples como hemos visto hasta ahora o depender de otras variables, por ejemplo:&lt;/p&gt;

&lt;p align="left"&gt;&lt;a href="http://kartones.net/blogs/jadengine/imagen6_0FE6CEB1.png"&gt;&lt;img src="http://kartones.net/blogs/jadengine/imagen6_thumb_68AC857B.png" style="border-width:0px;display:block;float:none;margin-left:auto;margin-right:auto;" title="imagen6" alt="imagen6" width="507" border="0" height="355" /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p align="left"&gt;Ahora la dureza de la Espada depende de su peso también. Para resolver esto la evaluación de variables se ejecutará de la siguiente manera:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;div align="left"&gt;Cuando se comienza a evaluar una variable se apunta en una tabla de variables calculadas con el valor de menos infinito.&lt;/div&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;div align="left"&gt;Si esta variable tiene un modificador que contiene una variable, se consulta a la tabla de variables ya calculadas.&lt;/div&gt;

    &lt;ul&gt;
      &lt;li&gt;
        &lt;div align="left"&gt;Si el valor de la variable es menos infinito hay una referencia circular (variable = variable) y el valor no se puede resolver. Excepción.&lt;/div&gt;
      &lt;/li&gt;

      &lt;li&gt;
        &lt;div align="left"&gt;Si es otra cosa se devuelve el valor y se continúa evaluando la variable actual.&lt;/div&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;div align="left"&gt;Si la variable no se encuentra en la tabla de variables ya calculadas se inicia una nueva evaluación para esa variable (vuelta al principio de este proceso).&lt;/div&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;div align="left"&gt;Cuando se termina de calcular el valor de una variable se actualiza en la tabla.&lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p align="left"&gt;La clase &lt;b&gt;Evaluator&lt;/b&gt; es la que se encarga de la búsqueda de modificadores y evaluación de variables.&lt;/p&gt;

&lt;p align="left"&gt;El código fuente de todo este jaleo se puede descargar desde este &lt;a href="http://kartones.net/files/folders/gamesources/entry37098.aspx"&gt;link&lt;/a&gt; (está bajo licencia MIT así que se puede hacer cualquier cosa con él). El zip contiene una solución de Visual Studio 2008 (C#) que está compuesta de dos proyectos:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;div align="left"&gt;&lt;b&gt;GravityAge.Statecraft.Core:&lt;/b&gt; el código de los prototipos y la evaluación de variables. Está bastante comentado así que debería ser fácil de comprender si se ha entendido este artículo.&lt;/div&gt;
  &lt;/li&gt;

  &lt;li&gt;
    &lt;div align="left"&gt;&lt;b&gt;GravityAge.Statecraft.Tests:&lt;/b&gt; unas cuantas pruebas unitarias para comprobar que todo está más o menos bien (debería hacer más, pero de momento con estas me basta). Hay una prueba que no se pasa (comprobar que una expresión infijo está bien formada) pero no sé como hacer que el parser se de cuenta de eso sin complicarme la vida demasiado, así que dejo el test roto para que no se me olvide que algún día debería solucionarlo.&lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;&lt;img src="http://kartones.net/aggbug.aspx?PostID=37099" width="1" height="1"&gt;&lt;img src="http://feeds.feedburner.com/~r/JadEngineBlog/~4/O9uug9nrBt8" height="1" width="1"/&gt;</description><category domain="http://kartones.net/blogs/jadengine/archive/tags/Statecraft/default.aspx">Statecraft</category><category domain="http://kartones.net/blogs/jadengine/archive/tags/RPG/default.aspx">RPG</category><feedburner:origLink>http://kartones.net/blogs/jadengine/archive/2009/02/09/implementando-el-reglamendo-de-un-rpg.aspx</feedburner:origLink></item></channel></rss>
