<?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.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:media="http://search.yahoo.com/mrss/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Codingly</title>
	
	<link>http://codingly.com</link>
	<description>Par Romain Verdier</description>
	<lastBuildDate>Wed, 21 Oct 2009 17:44:40 +0000</lastBuildDate>
	<generator>http://wordpress.com/</generator>
	<language>fr</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain="codingly.com" port="80" path="/?rsscloud=notify" registerProcedure="" protocol="http-post" />
<image>
		<url>http://www.gravatar.com/blavatar/62c090a2ec42be744d871177bd874854?s=96&amp;d=http://s.wordpress.com/i/buttonw-com.png</url>
		<title>Codingly</title>
		<link>http://codingly.com</link>
	</image>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" href="http://feeds.feedburner.com/Codingly" type="application/rss+xml" /><feedburner:emailServiceId>Codingly</feedburner:emailServiceId><feedburner:feedburnerHostname>http://feedburner.google.com</feedburner:feedburnerHostname><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>Switch sur un type en C#</title>
		<link>http://feedproxy.google.com/~r/Codingly/~3/TPPrSnIJYu0/</link>
		<comments>http://codingly.com/2009/10/19/switch-sur-un-type-en-c/#comments</comments>
		<pubDate>Mon, 19 Oct 2009 18:41:39 +0000</pubDate>
		<dc:creator>Romain Verdier</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://codingly.com/?p=872</guid>
		<description><![CDATA[Si vous avez besoin de faire un switch sur un type en C#, la première chose qu&#8217;il vous faut faire est de vous demander si vous avez besoin de faire un switch sur un type. Ensuite, demandez-vous si vous avez vraiment besoin de faire un switch sur un type, et forcez-vous à imaginer une solution [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=872&subd=romainverdier&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Si vous avez besoin de faire un switch sur un type en C#, la première chose qu&#8217;il vous faut faire est de vous demander si vous avez besoin de faire un switch sur un type. Ensuite, demandez-vous si vous avez <em>vraiment </em>besoin de faire un switch sur un type, et forcez-vous à imaginer une solution tirant partie du polymorphisme (c&#8217;est <em>presque</em> toujours possible). Si pour une raison quelconque (imaginons-la tout de même légitime), vous ne pouvez pas faire autrement, alors voici ce qu&#8217;il faut éviter de faire :<br />
<span id="more-872"></span></p>
<pre class="brush: csharp;">
    switch(expression.GetType().FullName)
    {
        case &quot;System.Linq.Expressions.ConstantExpression&quot;:
            VisitConstantExpression((ConstantExpression) expression);
            break;
        case &quot;System.Linq.Expressions.MemberExpression&quot;:
            VisitMemberExpression((MemberExpression) expression);
            break;
        case &quot;System.Linq.Expressions.MethodCallExpression&quot;:
            VisitMethodCallExpression((MethodCallExpression) expression);
            break;
        case &quot;System.Linq.Expressions.LambdaExpression&quot;:
            VisitLambdaExpression((LambdaExpression) expression);
            break;
        default:
            VisitExpression(expression);
            break;
    }
</pre>
<p>Aussi, si j&#8217;étais comme tout le monde (note: je ne suis pas comme tout le monde), je ferais une blague à propos de Dieu qui tue des animaux mignons à chaque fois que vous écrivez quelque chose comme :</p>
<pre class="brush: csharp;">
    if(expression is ConstantExpression)
        VisitConstantExpression((ConstantExpression)expression);
    else if (expression is MemberExpression)
        VisitMemberExpression((MemberExpression)expression);
    else if (expression is MethodCallExpression)
        VisitMethodCallExpression((MethodCallExpression)expression);
    else if (expression is LambdaExpression)
        VisitLambdaExpression((LambdaExpression)expression);
    else
        VisitExpression(expression);
</pre>
<p>La bonne solution, même si elle paraitra moins concise aux plus taquins d&#8217;entre vous, est la suivante :</p>
<pre class="brush: csharp;">
    var constantExpression = expression as ConstantExpression;
    if (constantExpression != null)
    {
        VisitConstantExpression(constantExpression);
        return;
    }

    var memberExpression = expression as MemberExpression;
    if (memberExpression != null)
    {
        VisitMemberExpression(memberExpression);
        return;
    }

    var methodCallExpression = expression as MethodCallExpression;
    if (methodCallExpression != null)
    {
        VisitMethodCallExpression(methodCallExpression);
        return;
    }

    var lambdaExpression = expression as LambdaExpression;
    if (lambdaExpression != null)
    {
        VisitLambdaExpression(lambdaExpression);
        return;
    }

    VisitExpression(expression);
</pre>
<p>Le safe cast évite la redondance <code>is</code> + cast. Rendons tout de même à césar ce qui est aux taquins : c&#8217;est un peu verbeux. Heureusement, il est assez facile de factoriser ce genre de code. J&#8217;utilise pour ma part une implémentation à base de méthodes d&#8217;extensions, qui ressemble à :</p>
<pre class="brush: csharp;">
    public class Switch
    {
        public object Target { get; set; }

        public Switch(object target)
        {
            this.Target = target;
        }
    }

    public static class SwitchExtensions
    {
        public static Switch Case&lt;T&gt;(this Switch @this, Action&lt;T&gt; action) where T : class
        {
            if (@this == null)
                return null;

            var t = @this.Target as T;
            if (t == null)
                return @this;

            action(t);
            return null;
        }

        public static void Default(this Switch @this, Action action)
        {
            if (@this == null)
                return;

            action();
        }
    }
</pre>
<p>On retombe alors à l&#8217;utilisation sur quelque chose de concis et lisible :</p>
<pre class="brush: csharp;">
    new Switch(expression)
        .Case&lt;ConstantExpression&gt;(VisitConstantExpression)
        .Case&lt;MemberExpression&gt;(VisitMemberExpression)
        .Case&lt;MethodCallExpression&gt;(VisitMethodCallExpression)
        .Default(() =&gt; VisitExpression(expression));
</pre>
<p>Chaque case prend un délégué en argument. Ici, comme <code>Action&lt;T&gt;</code> matche à chaque fois la signature des méthodes que je veux appeler (<code>Visit</code>*), je passe directement les method groups. Notez qu&#8217;il est tout à fait possible de faire autrement :</p>
<pre class="brush: csharp;">
    new Switch(expression)
        .Case&lt;MemberExpression&gt;(e =&gt; Console.WriteLine(&quot;MemberExpression : &quot; + e))
        .Case&lt;MethodCallExpression&gt;(e =&gt;
                                    {
                                        Console.WriteLine(&quot;Rofl&quot;);
                                        VisitMethodCallExpression(e);
                                        Console.WriteLine(&quot;Lfor&quot;);
                                    });
</pre>
<p>Enfin, pour ne pas que vous vous sentiez trop lésés par cet articlet, voici en prime une photo de pingouin :</p>
<p><img src="http://romainverdier.files.wordpress.com/2009/10/animated-tattoo-1.jpg?w=200&#038;h=182" alt="Rhino.Tattoo.dll" title="Rhino.Tattoo.dll" width="200" height="182" class="alignleft size-full wp-image-875" /></p>
Posted in Posts Tagged: .NET, C# <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/romainverdier.wordpress.com/872/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/romainverdier.wordpress.com/872/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/romainverdier.wordpress.com/872/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/romainverdier.wordpress.com/872/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/romainverdier.wordpress.com/872/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/romainverdier.wordpress.com/872/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/romainverdier.wordpress.com/872/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/romainverdier.wordpress.com/872/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/romainverdier.wordpress.com/872/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/romainverdier.wordpress.com/872/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=872&subd=romainverdier&ref=&feed=1" /></div><img src="http://feeds.feedburner.com/~r/Codingly/~4/TPPrSnIJYu0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codingly.com/2009/10/19/switch-sur-un-type-en-c/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb0ee4bde49708f4be24a02a5d59e52e?s=96&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">Romain</media:title>
		</media:content>

		<media:content url="http://romainverdier.files.wordpress.com/2009/10/animated-tattoo-1.jpg" medium="image">
			<media:title type="html">Rhino.Tattoo.dll</media:title>
		</media:content>
	<feedburner:origLink>http://codingly.com/2009/10/19/switch-sur-un-type-en-c/</feedburner:origLink></item>
		<item>
		<title>Tout ce que vous n’avez pas besoin de savoir au sujet du mot clé event</title>
		<link>http://feedproxy.google.com/~r/Codingly/~3/ZI0JQCOQE64/</link>
		<comments>http://codingly.com/2009/08/17/tout-ce-que-vous-navez-pas-besoin-de-savoir-au-sujet-du-mot-cle-event/#comments</comments>
		<pubDate>Mon, 17 Aug 2009 19:23:03 +0000</pubDate>
		<dc:creator>Romain Verdier</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://codingly.com/?p=797</guid>
		<description><![CDATA[Vous ne vous êtes jamais demandé à quoi servait, en C#, le mot clé event ? Moi oui. Et je vais même jusqu&#8217;à poser la question d&#8217;une certaine façon aux gens qui m&#8217;entourent, sauf peut-être dans la ligne 2 du métro :
&#8211;  &#160;A quoi ça sert, le mot clé event ?
&#8211;  &#160;Bah, à [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=797&subd=romainverdier&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Vous ne vous êtes jamais demandé à quoi servait, en C#, le mot clé <code>event</code> ? Moi oui. Et je vais même jusqu&#8217;à poser la question d&#8217;une certaine façon aux gens qui m&#8217;entourent, sauf peut-être dans la ligne 2 du métro :</p>
<blockquote><p>&#8211;  &nbsp;A quoi ça sert, le mot clé event ?<br />
&#8211;  &nbsp;Bah, à déclarer des events.<br />
&#8211;  &nbsp;Oui, mais ça marche pas sans le mot clé event ? En écrivant juste, par exemple :<br />
<code>&nbsp;&nbsp;public EventHandler Click;</code><br />
&#8211;  &nbsp;Heu, si, je crois.<br />
&#8211;  &nbsp;Donc, à quoi ça sert, le mot clé event ?<br />
&#8211;  &nbsp;T&#8217;es relou, dégage.</p></blockquote>
<p>Notez qu&#8217;à l&#8217;oral, il n&#8217;y a pas la coloration syntaxique. Je suppose que c&#8217;est ce qui conduit assez régulièrement mes interlocuteurs à être désagréables. (J&#8217;aime pas les gens désagréables !)</p>
<p><span id="more-797"></span></p>
<p>Au risque donc que vous commenciez à m&#8217;appeler Monsieur Mauclet, j&#8217;ai bien envie de regrouper dans ce post les principales différences qui existent entre :</p>
<pre class="brush: csharp;">public EventHandler Click;</pre>
<p>Et :</p>
<pre class="brush: csharp;">public event EventHandler Click;</pre>
<p>Et de combattre au passage certaines confusions, parce que je me sens l&#8217;âme d&#8217;un chevalier en ce moment.</p>
<p>Tout d&#8217;abord &#8212; et c&#8217;est la différence fondamentale dont découle la plupart des autres &#8212; un event (syntaxiquement assimilable à un champ de type delegate modifié par le mot clé <code>event</code>) n&#8217;est pas un champ. Il s&#8217;agit plutôt d&#8217;une sorte de propriété un peu spéciale revêtant une sémantique particulière : un event est explicitement, heh, un évènement. </p>
<p>Concrètement, écrire :</p>
<pre class="brush: csharp;">
public event EventHandler Click;
</pre>
<p> Est équivalent à :</p>
<pre class="brush: csharp;">
private EventHandler click;
public event EventHandler Click
{
	add { this.click += value; }
	remove { this.click -= value; }
}
</pre>
<p>Le code ci-dessus est valide en C#. Par défaut, un évènement possède des &#8220;accesseurs&#8221;, <code>add</code> et <code>remove</code>, qui permettent respectivement d&#8217;ajouter et de supprimer des handlers à un champ privé, de type delegate. Notez qu&#8217;il s&#8217;agit ici de l&#8217;implémentation générée par le compilateur lorsque vous utilisez la déclaration classique d&#8217;un event, mais il est tout à fait possible de changer cette implémentation : vous êtes en effet libre de mettre ce que vous voulez dans le <code>add</code> et le <code>remove</code>. A vrai dire, un event n&#8217;est <em>que</em> ce couple <code>add</code>/<code>remove</code>.</p>
<p>Exemple <code>!utile</code> : </p>
<pre class="brush: csharp;">
private EventHandler click;
private int handlerCount;
public event EventHandler Click
{
	add
	{
		this.click += value;
		this.handlerCount++;
	}
	remove
	{
		this.click -= value;
		this.handlerCount--;
	}
}
</pre>
<p>Il est intéressant de faire l&#8217;analogie entre la façon usuelle de déclarer un event et l&#8217;écriture d&#8217;une propriété automatique. Dans les deux cas, le compilateur fait le grunt work, et se charge donc de générer le backing field encapsulé par l&#8217;event ou la propriété, ainsi que la logique associée (affectation/lecture de la valeur ou ajout/suppression du handler), parce que la plupart du temps, c&#8217;est effectivement ce que l&#8217;on désire. Dans les deux cas, au risque de me répéter, il est possible de reprendre la main et de faire ce que l&#8217;on veut en proposant une implémentation différente des accesseurs (<code>get</code>/<code>set</code> pour les propriétés, <code>add</code>/<code>remove</code> pour les events).</p>
<p>En résumé, un event n&#8217;est pas un champ, un delegate, ou un truc de facebook ; non, <strong>un event en C# est un moyen d&#8217;exposer de façon normalisée, deux méthodes permettant d&#8217;enregistrer/désenregistrer des handlers</strong>. C&#8217;est tout.</p>
<p>Je crois qu&#8217;il faut bien faire la différence entre ce qu&#8217;est un event par définition, et ce que le compilateur génère par défaut pour nous aider. On peut très bien déclarer un event sans avoir de backing field, comme c&#8217;est aussi le cas pour les propriétés. Un-event-c&#8217;est-deux-méthodes.</p>
<p>Bon.</p>
<p>Après ce petit rappel, on devrait se sentir un peu plus à l&#8217;aise pour commencer l&#8217;énumération inutile de tout ce qui distingue plus ou moins évidemment un <code>event</code> d&#8217;un Champ Public De Type Delegate (CPDTD).</p>
<h3>Protection</h3>
<p>Lorsque vous exposez un CPDTD, n&#8217;importe qui est capable de le référencer et de le manipuler en tant que tel. Ce n&#8217;est pas le cas lorsque vous déclarez un event, puisque seules deux méthodes d&#8217;ajout/suppression de handler sont exposées. Du coup, l&#8217;invocation d&#8217;un event est restreinte : seul le type qui porte l&#8217;évènement peut déclencher ce dernier, les autres types devant se contenter de fournir leurs handlers en utilisant modestement les accesseurs.</p>
<p>Attention, même les types dérivés perdent le privilège d&#8217;invocation; on devra donc la plupart prévoir une méthode <code>protected</code> pour contourner la limitation. </p>
<h3>Interfaces</h3>
<p>Puisqu&#8217;un event-c&#8217;est-deux-méthodes, il peut apparaitre dans une interface, alors qu&#8217;un CPDTD, non. C&#8217;est très important, et très logique. Il est compréhensible en effet qu&#8217;on puisse s&#8217;engager à &#8220;exposer&#8221; deux méthodes dans un contrat, mais pas un champ.</p>
<h3>Polymorphisme</h3>
<p>Puisqu&#8217;un event-c&#8217;est-deux-méthodes, toujours, on peut parler de polymorphisme, et appliquer aux events les modifiers qu&#8217;il est habituellement possible d&#8217;appliquer aux méthodes. Implicitement, ils concerneront les deux accesseurs <code>add</code> et <code>remove</code>. Cela signifie qu&#8217;un event peut être <code>abstract</code>, <code>virtual</code> ou même <code>sealed</code>. De même, on peut overrider ou redéfinir un event à l&#8217;aide des mots clés <code>override</code> et <code>new</code>.</p>
<h3>Pas le droit lol</h3>
<p>Le fait qu&#8217;un event ait toujours des accesseurs (<code>add</code>/<code>remove</code>) implique que les fonctions correspondantes existent déjà. Ainsi, il est impossible d&#8217;écrire :</p>
<pre class="brush: csharp;">
public event EventHandler Click;

public void add_Click(EventHandler handler) {} // Erreur : signature existante
public void remove_Click(EventHandler handler) {} // Erreur : signature existante
</pre>
<h3>Opérateurs</h3>
<p>Lorsqu&#8217;utilisés avec les delegates, les opérateurs <code>+=</code> et <code>-=</code> ne sont pas interprétés comme la combinaison condensée d&#8217;une addition/soustraction + une affectation. le type <code>Delegate</code> ne surcharge d&#8217;ailleurs ni l&#8217;opérateur <code>+</code>, ni l&#8217;opérateur <code>-</code>. En fait, le compilateur remplace <code>+=</code> et <code>-=</code> par les appels respectifs aux méthodes statiques <code>Delegate.Combine</code> et <code>Delegate.Remove</code>, qui retournent de nouvelles instances de délégués. (Un délégué est immutable)</p>
<p>Par contre, lorqu&#8217;on utilise <code>+=</code> et <code>-=</code> pour ajouter/supprimer un handler à un event, le compilateur travaille différemment et se charge d&#8217;appeller directement les accesseurs de l&#8217;évènement.</p>
<p>Si <code>Click</code> est un CPDTD :</p>
<pre class="brush: csharp;">
button.Click += OnClick;
// Compilé en :
// button.Clik = (EventHandler) Delegate.Combine(button.Clik, new EventHandler(OnClick));
</pre>
<p>Si <code>Click</code> est un event :</p>
<pre class="brush: csharp;">
button.Click += OnClick;
// Compilé en :
// button.add_Click(new EventHandler(OnClick));
</pre>
<h3>Warnings</h3>
<p>Puisqu&#8217;il est uniquement possible de déclencher un évènement à l&#8217;intérieur de la classe qui contient sa déclaration, le compilateur est capable de lever un warning lorsqu&#8217;il ne détecte aucune invocation de l&#8217;évènement.</p>
<h3>Evaluation</h3>
<p>En C#, une affectation est une expression évaluable. On peut écrire, par exemple :</p>
<pre class="brush: csharp;">
int i = 12;
int j = i = 6; // (i = 6) est évalué, de type int, donc le code est valide et j vaudra 6.
</pre>
<p>De même, lorsque Click est un CPDTD, il est possible décrire :</p>
<pre class="brush: csharp;">EventHandler handler = button.Click += OnClick;</pre>
<p>Car l&#8217;expression <code>button.Click += OnClick</code> est de type <code>EventHandler</code>.</p>
<p>Mais dans le cas où <code>Click</code> est un event, <code>button.Click += OnClick</code> est de type <code>void</code>, du coup le code précédent ne compile pas.</p>
<h3>Reflection</h3>
<p>Si on veut accéder à un CPDTD par la réflexion, on utilise la méthode <code>GetField</code> ou <code>GetFields</code>. Mais comme les events sont des animaux bien différents, il existe les méthodes <code>GetEvent</code> et <code>GetEvents</code>, qui retournent des instances d&#8217;<code>EventInfo</code>. J&#8217;ai insisté là dessus précedemment : la notion d&#8217;event n&#8217;est liée à celle de backing field que parce qu&#8217;il s&#8217;agit d&#8217;une association constatée dans 99% des implémentations, mais c&#8217;est tout. Il est impossible d&#8217;optenir les métadonnées relatives au backing field d&#8217;un event à partir de son <code>EventInfo</code>, tout comme il est impossible d&#8217;obtenir les métadonnées relatives au backing field d&#8217;une propriété à partir de son <code>PropertyInfo</code>.</p>
<p>Enfin si, <a href="http://evain.net/blog/articles/2009/05/01/getting-the-field-backing-a-property-using-reflection">c&#8217;est possible</a>, mais chut.</p>
<h3>Interop</h3>
<p>Si vous kiffez COM, sachez que les CPDTD ne vous seront d&#8217;aucune utilité au cas où vous chercheriez à interopérer avec des évènements COM. Il faudra forcément utiliser des events. Et ne me dites pas que c&#8217;est évident<strike>, où je vous tue.</strike></p>
<h3>Doudounotte</h3>
<p>Microsoft propose une guideline relative aux events :</p>
<blockquote><p>&#8230;the delegate type used for an event should take two parameters, an &#8220;object source&#8221; parameter indicating the source of the event, and an &#8220;e&#8221; parameter that encapsulates any additional information about the event. The type of the &#8220;e&#8221; parameter should derive from the EventArgs class. For events that do not use any additional information, the .NET Framework has already defined an appropriate delegate type: EventHandler.</p></blockquote>
<p>Ce n&#8217;est qu&#8217;un encouragement, hein, vous êtes libre d&#8217;avoir des events de type <code>Action&lt;Func&lt;Dictionary&lt;string, List&lt;uint&gt;&gt;, Guid&gt;, bool&gt;</code> si vous le souhaitez. Néanmoins, l&#8217;idée est louable, puisque si le conseil est suivi, la contravariance permettrait à la méthode suivante de devenir un handler universel :</p>
<pre class="brush: csharp;">
public void OnEvent(object sender, EventArgs e)
{
}
</pre>
<p>Je suppose que c&#8217;est l&#8217;ambition très secrète de toutes les méthodes du monde. En tout cas, si j&#8217;étais une méthode, l&#8217;idée me séduirait.</p>
<h3>Synchronisation</h3>
<p>Pour les events, lorsqu&#8217;on laisse le compilateur générer le backing field et les accesseurs, ces derniers seront automatiquement synchronisés. Le compilateur associera en effet l&#8217;attribut <code>MethodImpl</code> avec l&#8217;option <code>MethodImplOptions.Synchronized</code> aux méthodes <code>add</code> et <code>remove</code>, ce qui est fonctionnellement équivalent à prendre un lock sur l&#8217;instance ou le type, selon si l&#8217;event est ou non statique.</p>
<p>Par contre, si vous préférez fournir votre propre implémentation pour les accesseurs, ce sera à vous de prévoir la synchronisation en utilisant un lock manuellement, si nécessaire.</p>
<p><em>Merci <a href="http://patricelamarche.net/">Patrice</a> !</em></p>
<h3>Menteur</h3>
<p>Si un event n&#8217;est que deux méthodes, comment se fait-il alors, gros malin, que l&#8217;on puisse écrire et compiler :</p>
<pre class="brush: csharp;">
public event EventHandler Click;

public void ICanHazInvokashun()
{
    Click(this, EventArgs.Empty);
}
</pre>
<p>En effet, un évènement est bien invocable. Ca voudrait dire que le compilateur est capable de tricher, et d&#8217;appeler sournoisement la méthode <code>Invoke</code> sur le champ privé caché ? Et bien oui. Le pseudo IL du corps de <code>ICanHazInvokashun</code> ressemble à :</p>
<pre class="brush: csharp;">
ldarg.0
ldfld class System.EventHandler Button::Click
ldarg.0
ldsfld class System.EventArgs System.EventArgs::Empty
callvirt instance void System.EventHandler::Invoke(object, class System.EventArgs)
ret
</pre>
<p>A la ligne 2 on constate que c&#8217;est bien un champ (<code>ldfld</code> = load field) qui est poussé sur le pile et sur lequel on appelle la méthode <code>Invoke</code> (ligne 5). A quoi d&#8217;autre pouvions-nous nous attendre ?</p>
<p>Si on décide de fournir une implémentation différente pour <code>add</code> et <code>remove</code>, le compilateur ne devrait plus être en mesure de permettre l&#8217;invocation directe de l&#8217;évènement avec la même syntaxe :</p>
<pre class="brush: csharp;">
public event EventHandler Click
{
    add { /* rien */ } remove { /* pas mieux */ }
}

public void ICanHazInvokashun()
{
    Click(this, EventArgs.Empty); // Haha j't'ai foolé, sale compiler.
}
</pre>
<p>Effectivement, il n&#8217;est plus possible de compiler la ligne 8, et on obtient le message d&#8217;erreur généralement réservé aux utilisateurs du type qui expose l&#8217;évènement :</p>
<blockquote><p>The event &#8216;Button.Click&#8217; can only appear on the left hand side of += or -=</p></blockquote>
<p>Voilà. Certes, c&#8217;était un post un peu facile, et tout ça n&#8217;est pas très excitant. Mais après tout, qu&#8217;est-ce qui peut bien être excitant en C# ? On parle d&#8217;un <em>langage de programmation</em> ! Alors à moins d&#8217;être un fanboy, etc.</p>
Posted in Articles Tagged: .NET, C# <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/romainverdier.wordpress.com/797/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/romainverdier.wordpress.com/797/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/romainverdier.wordpress.com/797/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/romainverdier.wordpress.com/797/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/romainverdier.wordpress.com/797/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/romainverdier.wordpress.com/797/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/romainverdier.wordpress.com/797/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/romainverdier.wordpress.com/797/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/romainverdier.wordpress.com/797/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/romainverdier.wordpress.com/797/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=797&subd=romainverdier&ref=&feed=1" /></div><img src="http://feeds.feedburner.com/~r/Codingly/~4/ZI0JQCOQE64" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codingly.com/2009/08/17/tout-ce-que-vous-navez-pas-besoin-de-savoir-au-sujet-du-mot-cle-event/feed/</wfw:commentRss>
		<slash:comments>10</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb0ee4bde49708f4be24a02a5d59e52e?s=96&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">Romain</media:title>
		</media:content>
	<feedburner:origLink>http://codingly.com/2009/08/17/tout-ce-que-vous-navez-pas-besoin-de-savoir-au-sujet-du-mot-cle-event/</feedburner:origLink></item>
		<item>
		<title>Je ne suis pas Joel Spolsky</title>
		<link>http://feedproxy.google.com/~r/Codingly/~3/ECvHYc-wIs0/</link>
		<comments>http://codingly.com/2009/08/05/je-ne-suis-pas-joel-spolsky/#comments</comments>
		<pubDate>Wed, 05 Aug 2009 13:53:01 +0000</pubDate>
		<dc:creator>Romain Verdier</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[ALT.NET]]></category>

		<guid isPermaLink="false">http://codingly.com/?p=747</guid>
		<description><![CDATA[Je ne sais pas si vous avez remarqué, mais Joel a carrément sauté le requin. Avant, son blog était maintenu, la plupart du temps drôle, et généralement intéressant. Maintenant, il ne poste plus rien, ou très rarement. Pire : souvent il ne poste que pour signaler qu&#8217;il vient d&#8217;écrire un article sur Inc. Du coup [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=747&subd=romainverdier&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Je ne sais pas si vous avez remarqué, mais <a href="http://www.joelonsoftware.com/">Joel</a> a carrément <a href="http://en.wikipedia.org/wiki/Jumping_the_shark">sauté le requin</a>. Avant, son blog était maintenu, la plupart du temps drôle, et généralement intéressant. Maintenant, il ne poste plus rien, ou très rarement. Pire : souvent il ne poste que pour signaler qu&#8217;il vient d&#8217;écrire un article sur <a href="http://www.inc.com/">Inc.</a> Du coup ses billets ressemblent à <a href="http://www.joelonsoftware.com/items/2009/06/10b.html">ça</a> (sur 8 lignes) :</p>
<blockquote><p>From my latest Inc. column : &#8220;Blah blah blah&#8221;</p></blockquote>
<p>Bon, moi, je ne suis pas Joel Spolsky car je n&#8217;ai pas tenu 10 ans avant de sauter le requin.<br />
<span id="more-747"></span><br />
Extrait de <a href="http://www.altnetfr.org/2009/08/05/compte-rendu-rencontre-altnet-16-winddbg/">mon dernier compte-rendu sur altnetfr.org</a> :</p>
<blockquote><p>Par contre, Yann ne sait pas coder :</p>
<p><code>for(int i=0; i&lt; 100000000; i++)<br />
{<br />
&nbsp;&nbsp;&nbsp;if(!list.Contains(Guid.NewGuid().ToString()))<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;list.Add(Guid.NewGuid().ToString());<br />
}</code></p>
<p>Il faut probablement avoir une maladie mentale pour écrire ça ! C&#8217;est en tout cas ce que j&#8217;ai pensé sur le coup, en pouffant sur ma chaise (j’étais au fond de la salle). Ensuite, je ne sais plus si je l&#8217;ai compris de moi même ou si Yann a dû le préciser d’un air atterré, mais il avait fait exprès d’écrire ça. Parce que d&#8217;autres ne font pas exprès, et que ça pose des problèmes.</p></blockquote>
<p>C&#8217;était au sujet de la dernière rencontre ALT.NET parisienne, où <a href="http://blog.polom.com/">Yann Schwartz</a> nous parlait de Windbg et d&#8217;autres trucs. C&#8217;était très bien.</p>
Posted in Posts Tagged: .NET, ALT.NET <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/romainverdier.wordpress.com/747/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/romainverdier.wordpress.com/747/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/romainverdier.wordpress.com/747/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/romainverdier.wordpress.com/747/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/romainverdier.wordpress.com/747/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/romainverdier.wordpress.com/747/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/romainverdier.wordpress.com/747/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/romainverdier.wordpress.com/747/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/romainverdier.wordpress.com/747/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/romainverdier.wordpress.com/747/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=747&subd=romainverdier&ref=&feed=1" /></div><img src="http://feeds.feedburner.com/~r/Codingly/~4/ECvHYc-wIs0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codingly.com/2009/08/05/je-ne-suis-pas-joel-spolsky/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb0ee4bde49708f4be24a02a5d59e52e?s=96&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">Romain</media:title>
		</media:content>
	<feedburner:origLink>http://codingly.com/2009/08/05/je-ne-suis-pas-joel-spolsky/</feedburner:origLink></item>
		<item>
		<title>ALT.NET en France : Présentation AOP, c’est fait.</title>
		<link>http://feedproxy.google.com/~r/Codingly/~3/AAB-CmKBJwU/</link>
		<comments>http://codingly.com/2009/06/18/alt-net-en-france-presentation-aop-cest-fait/#comments</comments>
		<pubDate>Thu, 18 Jun 2009 08:09:28 +0000</pubDate>
		<dc:creator>Romain Verdier</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[ALT.NET]]></category>
		<category><![CDATA[AOP]]></category>

		<guid isPermaLink="false">http://codingly.com/?p=716</guid>
		<description><![CDATA[Je me demande si 91 slides valent 1000 mots. Vous pourrez essayer de vous faire une idée puisqu&#8217;elles sont disponibles ci-dessous. Je vous conseille de carrément télécharger la présentation si vous êtes intéressés par les animations, puisque certaines (lire : toutes) sont très logiquement tuées par SlideShare.
Bon, pour ma part j&#8217;ai trouvé que ça s&#8217;était [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=716&subd=romainverdier&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Je me demande si 91 slides valent 1000 mots. Vous pourrez essayer de vous faire une idée puisqu&#8217;elles sont disponibles ci-dessous. Je vous conseille de carrément télécharger la présentation si vous êtes intéressés par les animations, puisque certaines (lire : toutes) sont très logiquement tuées par SlideShare.</p>
<p>Bon, pour ma part j&#8217;ai trouvé que ça s&#8217;était plutôt bien passé considérant que je ne suis pas un speaker &#8211; au mieux un <a href="http://codingly.com/2008/12/29/degage-sale-programmeur/">sale programmeur</a> &#8211; même si j&#8217;imaginais une présentation un peu plus courte. J&#8217;ai parlé pendant 45 min, je crois, puis j&#8217;ai ouvert VS pour la &#8220;démo interactive&#8221; qui s&#8217;est un peu éternisée.</p>
<p>Je tiens encore à remercier <a href="http://fastconnect.fr/">FastConnect</a> pour la salle, l&#8217;organisation, le buffet, etc.<br />
<span id="more-716"></span><br />
<object type='application/x-shockwave-flash' wmode='transparent' data='http://static.slideshare.net/swf/ssplayer2.swf?id=1601593&#038;doc=aop-net-090618014706-phpapp01' width='720' height='590'><param name='movie' value='http://static.slideshare.net/swf/ssplayer2.swf?id=1601593&#038;doc=aop-net-090618014706-phpapp01' /><param name='allowFullScreen' value='true' /><param name='allowScriptAccess' value='always' /></object></p>
<p>En ce qui concerne le code des exemples, j&#8217;essaierai d&#8217;éditer ce post ultérieurement.</p>
<p><span class="edittag">Edit</span> Quelques liens en rapport :</p>
<ul>
<li><a href="http://codingly.com/2008/10/29/utiliser-laop-avec-postsharp-pour-implementer-inotifypropertychanged/">INotifyPropertyChanged avec PostSharp</a></li>
<li><a href="http://codingly.com/2008/11/10/introduction-a-monocecil-implementer-inotifypropertychanged/">INotifyPropertyChanged avec Mono.Cecil</a></li>
</ul>
<p><span class="edittag">Edit</span> Le <a href="http://www.altnetfr.org/2009/06/24/altnet-paris-14-compte-rendu-aop/">compte rendu de la soirée</a> est maintenant dispo sur le site ALT.NET Fr. Merci <a href="http://evain.net/blog/">Jb</a>.</p>
<p>N&#8217;hésitez pas à me faire part de vos critiques <em>positives</em>, puisque les autres, constructives ou pas, elles vexent. OK ?</p>
Posted in Posts Tagged: .NET, ALT.NET, AOP <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/romainverdier.wordpress.com/716/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/romainverdier.wordpress.com/716/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/romainverdier.wordpress.com/716/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/romainverdier.wordpress.com/716/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/romainverdier.wordpress.com/716/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/romainverdier.wordpress.com/716/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/romainverdier.wordpress.com/716/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/romainverdier.wordpress.com/716/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/romainverdier.wordpress.com/716/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/romainverdier.wordpress.com/716/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=716&subd=romainverdier&ref=&feed=1" /></div><img src="http://feeds.feedburner.com/~r/Codingly/~4/AAB-CmKBJwU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codingly.com/2009/06/18/alt-net-en-france-presentation-aop-cest-fait/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb0ee4bde49708f4be24a02a5d59e52e?s=96&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">Romain</media:title>
		</media:content>
	<feedburner:origLink>http://codingly.com/2009/06/18/alt-net-en-france-presentation-aop-cest-fait/</feedburner:origLink></item>
		<item>
		<title>ALT.NET en France : Présentation AOP à Paris le 17 juin</title>
		<link>http://feedproxy.google.com/~r/Codingly/~3/nYSO8FiGIR8/</link>
		<comments>http://codingly.com/2009/06/02/alt-net-en-france-presentation-aop-a-paris-le-17-juin/#comments</comments>
		<pubDate>Tue, 02 Jun 2009 21:18:28 +0000</pubDate>
		<dc:creator>Romain Verdier</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[ALT.NET]]></category>
		<category><![CDATA[Annonce]]></category>
		<category><![CDATA[AOP]]></category>

		<guid isPermaLink="false">http://codingly.com/?p=655</guid>
		<description><![CDATA[Avant toute chose : Non, je ne chercherai pas à justifier le rythme misérable de mes publications sur ce blog. Et non, je ne m&#8217;excuserai pas de tricher lamentablement en postant aujourd&#8217;hui quelque chose d&#8217;aussi, heu, bref.
Je voulais vous informer, ou plus probablement vous rappeler, que j&#8217;allais commettre une présentation sur l&#8217;AOP, le 17 juin, [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=655&subd=romainverdier&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Avant toute chose : Non, je ne chercherai pas à justifier le rythme misérable de mes publications sur ce blog. Et non, je ne m&#8217;excuserai pas de tricher lamentablement en postant aujourd&#8217;hui quelque chose d&#8217;aussi, heu, bref.</p>
<p>Je voulais vous informer, ou plus probablement vous rappeler, que j&#8217;allais commettre une présentation sur l&#8217;<a href="http://en.wikipedia.org/wiki/Aspect-oriented_programming">AOP</a>, le 17 juin, à l&#8217;occasion de la 14ème rencontre ALT.NET Parisienne. Vous trouverez les détails pratiques <a href="http://www.altnetfr.org/2009/05/28/altnet-paris-14-aspect-oriented-programming-aop/">sur notre joli site</a>. Merci à <a href="http://www.fastconnect.fr">FastConnect</a> qui sponsorise l&#8217;évènement.<br />
<span id="more-655"></span><br />
Il va sans dire que je serais plus à l&#8217;aise s&#8217;il n&#8217;y avait que 3 personnes qui jugeaient bon de se déplacer. Pourtant, je vais m&#8217;asseoir sur cette considération et vous inviter à venir nombreux. Plusieurs fois au cours des rencontres précédentes nous avons abordé la question de la programmation orientée aspect lors des discussions libres, et il semblerait donc que le sujet rende curieux, à défaut de préoccuper. Peut-être mérite-t-il que nous lui fassions plus de place le temps d&#8217;une soirée. Je ne sais pas encore exactement quel sera l&#8217;agenda, mais l&#8217;idée est de présenter l&#8217;AOP en tant que concept, de le confronter gentiment aux paradigmes traditionnels, avant de passer plus concrètement à l&#8217;étude des différentes techniques et outils qui existent en .NET.</p>
<p>D&#8217;aucuns pourraient penser que le sujet n&#8217;est pas spécialement ALT.NET.</p>
<p>Ce à quoi je répondrais :</p>
<blockquote><p>Certes, certes&#8230;</p></blockquote>
<p>Enfin. Si on compte uniquement sur Microsoft pour profiter de l&#8217;AOP on risque assez rapidement de se sentir à l&#8217;étroit. Il est possible de faire de l&#8217;AOP sans sortir de la BCL, oui, et il est possible de faire de l&#8217;AOP <em>un peu plus facilement</em> en débordant sur <a href="http://stackoverflow.com/questions/833729/built-in-aop-in-c-is-it-on-the-way/833919#833919">EntLib</a>. Cependant, les solutions les plus matures et les plus riches pour faire de l&#8217;AOP en .NET ne sont pas forcément estampillées Microsoft, ce qui risque de conduire l&#8217;utilisateur averti vers des frameworks plus spécialisés, open-source ou pas. Je veux parler de Castle.DynamicProxy, PostSharp, Linfu, Mono.Cecil, Spring.NET, etc.</p>
<p>Moi, je trouve que ça sent ALT.NET.</p>
<p>Bref, j&#8217;espère que cette rencontre verra naitre un débat et que nous pourrons collecter quelques retours d&#8217;expériences, comparer nos approches, bailler, etc. Encore une fois, toutes les infos sont disponibles sur le site <a href="http://www.altnetfr.org/">altnetfr</a>, à <a href="http://www.altnetfr.org/2009/05/28/altnet-paris-14-aspect-oriented-programming-aop/">cette adresse</a>.</p>
<p>Pensez à <a href="http://www.doodle.com/nd4f57ugtsddqk36">vous inscrire</a>, et n&#8217;hésitez pas à faire passer l&#8217;info.</p>
Posted in Posts Tagged: .NET, ALT.NET, Annonce, AOP <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/romainverdier.wordpress.com/655/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/romainverdier.wordpress.com/655/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/romainverdier.wordpress.com/655/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/romainverdier.wordpress.com/655/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/romainverdier.wordpress.com/655/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/romainverdier.wordpress.com/655/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/romainverdier.wordpress.com/655/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/romainverdier.wordpress.com/655/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/romainverdier.wordpress.com/655/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/romainverdier.wordpress.com/655/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=655&subd=romainverdier&ref=&feed=1" /></div><img src="http://feeds.feedburner.com/~r/Codingly/~4/nYSO8FiGIR8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codingly.com/2009/06/02/alt-net-en-france-presentation-aop-a-paris-le-17-juin/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb0ee4bde49708f4be24a02a5d59e52e?s=96&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">Romain</media:title>
		</media:content>
	<feedburner:origLink>http://codingly.com/2009/06/02/alt-net-en-france-presentation-aop-a-paris-le-17-juin/</feedburner:origLink></item>
		<item>
		<title>Petit rappel sur le Disposing Pattern en C#</title>
		<link>http://feedproxy.google.com/~r/Codingly/~3/zMx02ykcfH8/</link>
		<comments>http://codingly.com/2009/04/01/petit-rappel-sur-le-disposing-pattern-en-c/#comments</comments>
		<pubDate>Wed, 01 Apr 2009 09:02:14 +0000</pubDate>
		<dc:creator>Romain Verdier</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[WTF]]></category>

		<guid isPermaLink="false">http://codingly.com/?p=641</guid>
		<description><![CDATA[Ca fait longtemps que je veux faire ce post, au sujet d&#8217;une question trop souvent négligée : le disposing pattern. On peut voir ça comme un petit rappel, ou un post à classer dans la catégorie &#8220;back to basics&#8221;. En deux mots, il s&#8217;agit de gérer correctement la libération des ressources non-managées, dans un programme [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=641&subd=romainverdier&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Ca fait longtemps que je veux faire ce post, au sujet d&#8217;une question trop souvent négligée : le <em>disposing pattern</em>. On peut voir ça comme un petit rappel, ou un post à classer dans la catégorie &#8220;back to basics&#8221;. En deux mots, il s&#8217;agit de gérer correctement la libération des ressources non-managées, dans un programme managé.</p>
<blockquote><p><strong>EDIT </strong>: Ce post est un poisson d&#8217;avril, évidemment. Il vaudrait mieux ne pas utiliser l&#8217;implémentation du disposing pattern proposée&#8230;</p></blockquote>
<p><span id="more-641"></span></p>
<h3>Quelques rappels</h3>
<p>On parle de code managé en .NET car on fait implicitement référence au garbage collector qui <em>gère automatiquement la mémoire</em>. Il n&#8217;est pas question de faire un cours sur le GC, mais retenez juste qu&#8217;il est très intelligent, et qu&#8217;il est <em>indépendant</em>. Tellement indépendant qu&#8217;on ne peut pas prévoir quand est-ce qu&#8217;il va réellement effectuer son recyclage. Par exemple, lorsque vous écrivez :</p>
<pre class="brush: csharp;">
public int Add(int a, int b)
{
    Calculator calculator = new Calculator();
    return calculator.Add(a, b);
};
</pre>
<p>Vous créez une nouvelle instance de <code>Calculator</code> qui sera référencée par la variable locale <code>calculator</code>. A la sortie de la méthode, la variable locale n&#8217;existe plus, et l&#8217;instance de <code>Calculator</code> n&#8217;est donc plus référencée. L&#8217;espace mémoire qu&#8217;elle occupe peut être récupéré, et le GC le sait. (Notez l&#8217;assonance.) Il y a un instant j&#8217;insistais sur l&#8217;indépendance du garbage collector : s&#8217;il sait qu&#8217;il peut libérer une instance, <strong>vous ne savez pas quand il le fera</strong>.</p>
<p>On considère que la collecte des miettes est indéterministe. Vous n&#8217;avez aucun moyen de savoir précisément quand le calculator que vous avez instancié précédemment sera collecté. Ca ne sera pas forcément à la sortie de la méthode, comme on pourrait naïvement s&#8217;y attendre ; ça peut être 47 ms ou 47 secondes après (pour caricaturer) et vous devriez même être heureux de ne pas avoir à vous en soucier.</p>
<p>Mais.</p>
<p>Tout n&#8217;est pas managé. Parfois, vous utilisez à partir d&#8217;objets managés des ressources non managées. Même si ça peut paraitre évident, il est bon de revenir là dessus. On parle de &#8220;ressource non managée&#8221; dans ce contexte pour décrire une ressource :</p>
<ul>
<li>Dont l&#8217;allocation est déclenchée à partir de votre code managé.</li>
<li>Qui doit être libérée.</li>
<li>Mais dont le garbage collector n&#8217;est pas responsable.</li>
</ul>
<p>Les handles de fichiers, les connexions de bases de données, les sockets réseau ou les références COM sont des exemples de ressources non managées.</p>
<h3>Comment implémenter le disposing pattern</h3>
<p>On se base sur l&#8217;interface <code>IDisposable</code>, et sur les destructeurs de C#. <code>IDisposable</code> expose une méthode <code>Dispose</code>, qui va détruire l&#8217;objet, et faire en sorte que sa mémoire soit désallouée du heap (et non pas de la pile comme je le vois souvent dans des blogs), surtout si on fait bien appel au mot clé <code>using</code> qui ne sert pas qu&#8217;à importer des namespaces.</p>
<p>Mais assez de théorie, passons au code. Imaginons la classe C# suivante, et regardons comment elle fait pour libérer le <code>IntPtr</code> qu&#8217;elle a en variable publique et qui constitue sa variable non managée dangereuse (attention aux memory leaks lol) :</p>
<blockquote><p><strong>EDIT </strong>: Ce post est un poisson d&#8217;avril, évidemment. Il vaudrait mieux ne pas utiliser l&#8217;implémentation du disposing pattern proposée&#8230;</p></blockquote>
<pre class="brush: csharp;">
public class MaClasseManagée : IDisposable // on implémente IDisposable
{
    private IntPtr m_Ressource_non_managée; // Attention !
	bool disposed = false; // pour savoir si la classe est libérée  

    public MaClasseManagée(IntPtr ptrnonmanagé)
    {
		if(ptrnonmanagé != null)
		{
			m_Ressource_non_managée = ptrnonmanagé; // allocation mémoire non managée
		}
		else // sinon
		{
			if (ptr.Equals(IntPtr.Zero) == true)
            {
                // on désalloue directement la mémoire du pointeur
				m_Ressource_non_managée = IntPtr.Zero
            }
			GC.CancelFullGCNotification(); // pas obligé, mais il vaut mieux
		}
    }

	public void FaireQuelqueChose()
	{
		// ici on utilise la ressource non managée qui a été allouée
		// ...
		// ...
	}

	// destruteur de la class
	~MaClasseManagée()
	{
		// partie un peu tricky : on interdit au CLR de supprimer l'instance
		// courante car ça a déjà été fait dans le Dispose d'IDisposable
		GC.SuppressFinalize(this);

		// on s'assure quand même qu'on garde pas de référence vers le pointeur
		m_Ressource_non_managée = IntPtr.Zero;
	}

	// methode dispose la plus importante
    public void Dispose()
    {
        if(!disposed)
        {
			// on appelle le garbage collector, et on force la libération de
			// tous les objets pour être certains de plus référencer des variables
			// non managées depuis C#
			GC.Collect();

			disposed = true; // déja disposé
        }
    }
}
</pre>
<p>Notez donc qu&#8217;il faut bien faire la différence entre le constructeur, le destructeur, et le dispose. Trop souvent les gens oublient l&#8217;un des trois, et compromettent du coup la sécurité de leur code.</p>
<p>A l&#8217;utilisation c&#8217;est simple :</p>
<pre class="brush: csharp;">
// mot clé using
using(MaClasseManagée obj = new MaClasseManagée())
{
	// manipuler obj
	obj.FaireQuelqueChose();
}
// à la sortie du bloc using, le garbage collector est appellé et libère le tas
// des instances de MaClasseManagée persistantes, donc, forcément avec notre
// pattern, des ressources non managées IntPtr aussi
</pre>
<p>Et voilà :)</p>
<p>Je compte faire un article bientôt sur une nouvelle façon d&#8217;appréhender cette problématique avec l&#8217;AOP, notamment dans les architectures distribuées où il y a trop de code à écrire pour qu&#8217;on puisse se permettre de perdre du temps avec ces considérations bas niveau dans un contexte économique délicat (c&#8217;est la crise !) qui nous force à économiser le temps et l&#8217;argent sans pour autant arrêter de produire des logiciels de qualité qui donneront satisfaction au client et permettront aux développeurs de ne pas s&#8217;arracher les cheveux sur des solutions de 50 projets où les autres ont fait n&#8217;importe quoi et qu&#8217;il faut quand même livrer coute que coute tant pis pour les nuits blanches (ça serait quand même un comble de ne plus être en mesure de maitriser son métier, ou de devoir arrêter la qualité sous prétexte que c&#8217;est les chefs de projets qui décident des planning sans rien comprendre de la technique alors que c&#8217;est la base).</p>
Posted in Posts Tagged: .NET, C#, WTF <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/romainverdier.wordpress.com/641/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/romainverdier.wordpress.com/641/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/romainverdier.wordpress.com/641/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/romainverdier.wordpress.com/641/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/romainverdier.wordpress.com/641/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/romainverdier.wordpress.com/641/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/romainverdier.wordpress.com/641/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/romainverdier.wordpress.com/641/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/romainverdier.wordpress.com/641/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/romainverdier.wordpress.com/641/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=641&subd=romainverdier&ref=&feed=1" /></div><img src="http://feeds.feedburner.com/~r/Codingly/~4/zMx02ykcfH8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codingly.com/2009/04/01/petit-rappel-sur-le-disposing-pattern-en-c/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb0ee4bde49708f4be24a02a5d59e52e?s=96&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">Romain</media:title>
		</media:content>
	<feedburner:origLink>http://codingly.com/2009/04/01/petit-rappel-sur-le-disposing-pattern-en-c/</feedburner:origLink></item>
		<item>
		<title>Nouveau site pour ALT.NET France</title>
		<link>http://feedproxy.google.com/~r/Codingly/~3/OGi0tfVaB4I/</link>
		<comments>http://codingly.com/2009/03/02/nouveau-site-pour-altnet-france/#comments</comments>
		<pubDate>Mon, 02 Mar 2009 10:21:03 +0000</pubDate>
		<dc:creator>Romain Verdier</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[ALT.NET]]></category>
		<category><![CDATA[Annonce]]></category>

		<guid isPermaLink="false">http://codingly.com/?p=626</guid>
		<description><![CDATA[Enfin ! Nous avions un groupe de discussion depuis le début, et nous squattions à droite et à gauche lorsqu&#8217;il était nécessaire de communiquer et de s&#8217;organiser, mais depuis quelques jours nous avons notre vrai portail. Un grand merci à Julien pour son travail, et à ceux qui ont commencé à contribuer à l&#8217;élaboration du [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=626&subd=romainverdier&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Enfin ! Nous avions un <a href="http://groups.google.com/group/parisaltnet">groupe de discussion</a> depuis le début, et nous squattions à droite et à gauche lorsqu&#8217;il était nécessaire de communiquer et de s&#8217;organiser, mais depuis quelques jours nous avons notre vrai portail. Un grand merci à <a href="http://www.thedotnetfrog.fr/">Julien</a> pour son travail, et à ceux qui ont commencé à contribuer à l&#8217;élaboration du contenu :</p>
<p><strong><a href="http://www.altnetfr.org/">www.altnetfr.org</a></strong></p>
<blockquote><p>ALT.Net est un groupe de développeurs .NET passionnés, cherchant à améliorer la façon dont les logiciels sont développés. Nous reconnaissons qu’il n’y a pas de solution unique à un problème mais qu’il y a une multitude d’alternatives pouvant être appliquées dans différentes situations.</p></blockquote>
<p><span id="more-626"></span></p>
<p>Le but était d&#8217;offrir une façade à la communauté ALT.NET de France. Jusqu&#8217;alors il fallait être spécialement motivé pour parvenir à comprendre ce qu&#8217;était ALT.NET, et encore un peu plus pour oser venir aux rencontres. Le nouveau site devrait donc répondre à ces deux besoins, en décrivant le mouvement et ses principes d&#8217;une part, et en proposant l&#8217;agenda des différents évènements que nous organisons d&#8217;autre part.</p>
<p>La dernière réunion a permis à Nicolas Roux et Frédéric Fadel de nous présenter <a href="http://aspectize.com/">Aspectize</a>, et <a href="http://www.altnetfr.org/2009/02/22/altnet-fr-10-aspectize-compte-rendu-par-gauthier/">un compte rendu</a> a déjà été posté par Gauthier. En Mars, <a href="http://www.altnetfr.org/2009/02/20/altnet-paris-11-test-driven-development/">il sera question de TDD</a>, et c&#8217;est Djamel Zouaoui et Frédéric Schäfer qui animeront la présentation dans les locaux d&#8217;Octo. Nous comptons continuer de la sorte en annonçant les réunions futures et en proposant des comptes-rendus régulièrement. N&#8217;hésitez d&#8217;ailleurs pas à soumettre vos contributions ; un effort collaboratif ne peut qu&#8217;être profitable.</p>
<p>Pour ceux qui ne sont pas spécialement enclins à rédiger des comptes-rendus ou à proposer des articles, notez qu&#8217;il existe un <a href="http://wiki.altnetfr.org/doku.php">wiki</a>, qui offre déjà à tous la possibilité de participer sans contrainte particulière à l&#8217;enrichissement des ressources ALT.NET en français.</p>
<p>Bref, vous êtes chaudement invités à :</p>
<ul>
<li>Ajouter altnetfr.org dans vos readers</li>
<li>Proposer vos comptes-rendus, vos articles, etc.</li>
<li>Venir à la prochaine réunion (et aux autres)</li>
<li>Faire passer le mot au sujet d&#8217;ALT.NET France !</li>
<ul>
Posted in Posts Tagged: ALT.NET, Annonce <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/romainverdier.wordpress.com/626/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/romainverdier.wordpress.com/626/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/romainverdier.wordpress.com/626/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/romainverdier.wordpress.com/626/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/romainverdier.wordpress.com/626/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/romainverdier.wordpress.com/626/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/romainverdier.wordpress.com/626/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/romainverdier.wordpress.com/626/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/romainverdier.wordpress.com/626/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/romainverdier.wordpress.com/626/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=626&subd=romainverdier&ref=&feed=1" /></div><img src="http://feeds.feedburner.com/~r/Codingly/~4/OGi0tfVaB4I" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codingly.com/2009/03/02/nouveau-site-pour-altnet-france/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb0ee4bde49708f4be24a02a5d59e52e?s=96&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">Romain</media:title>
		</media:content>
	<feedburner:origLink>http://codingly.com/2009/03/02/nouveau-site-pour-altnet-france/</feedburner:origLink></item>
		<item>
		<title>Si les types étaient des animaux, TypedReference serait un ornithorynque</title>
		<link>http://feedproxy.google.com/~r/Codingly/~3/-1ImBKH4ikg/</link>
		<comments>http://codingly.com/2009/01/15/si-les-types-etaient-des-animaux-typedreference-serait-un-ornithorynque/#comments</comments>
		<pubDate>Thu, 15 Jan 2009 00:08:29 +0000</pubDate>
		<dc:creator>Romain Verdier</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[CIL]]></category>
		<category><![CDATA[Optimisation]]></category>

		<guid isPermaLink="false">http://codingly.com/?p=535</guid>
		<description><![CDATA[Devinette : C&#8217;est un type valeur, mais on ne peut pas le caster en object. Il est impossible d&#8217;en déclarer des tableaux. On ne peut l&#8217;utiliser que pour typer les paramètres de méthodes et les variables locales. Il existe 4 mots clés non documentés en C# qui lui sont directement reliés, et autant d&#8217;opcodes en [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=535&subd=romainverdier&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Devinette : C&#8217;est un type valeur, mais on ne peut pas le caster en <code>object</code>. Il est impossible d&#8217;en déclarer des tableaux. On ne peut l&#8217;utiliser que pour typer les paramètres de méthodes et les variables locales. Il existe 4 mots clés non documentés en C# qui lui sont directement reliés, et autant d&#8217;opcodes en CIL. Il permet notamment le support des varargs, et exactement 8 personnes dans le monde se sont souciées plus de 5 min de son existence.</p>
<p>Je veux parler, bien évidemment, de <code><a href="http://www.urbandictionary.com/define.php?term=PITA">TypedReference</a></code>. Je vous propose de découvrir ce type à partir d&#8217;un exemple rigolo.<br />
<span id="more-535"></span></p>
<h3>Méthodes <em>varargs</em> et interopérabilité</h3>
<p>En C#, lorsqu&#8217;on veut définir une méthode à nombre de paramètres variables, on utilise la syntaxe suivante :</p>
<pre class="brush: csharp;">
public static double Average(params int[] values)
{
    double sum = 0;
    foreach (var i in values)
        sum += i;
    return sum / values.Length;
}
</pre>
<p>Notez le mot clé <code>params</code> qui permet l&#8217;appel de la méthode en passant un tableau en paramètre, ou en listant plus librement les arguments :</p>
<pre class="brush: csharp;">
var parameters = new int[]{45, 68, 97, 45};
ManagedClass.Average (parameters)
// ou bien
ManagedClass.Average (45, 68, 97, 45)
</pre>
<p>En <a href="http://en.wikipedia.org/wiki/C%2B%2B/CLI">C++ / CLI</a>, la syntaxe est un peu différente mais le principe est le même :</p>
<pre class="brush: cpp;">
double CodinglyInterop::CppCliLibrary::average(... array&lt;int,1&gt; ^values)
{
	double sum = 0;
	for each (int i  in values)
		sum += i;
	return sum/values-&gt;Length;
}
</pre>
<p>C&#8217;est pareil, en plus moche. On utilise &#8220;<code>...</code>&#8221; au lieu de &#8220;<code>params</code>&#8220;, et l&#8217;appelant peut passer un tableau ou une liste d&#8217;arguments :</p>
<pre class="brush: csharp;">
var parameters = new int[]{45, 68, 97, 45};
CppCliLibrary.average(parameters)
// ou bien
CppCliLibrary.average(45, 68, 97, 45)
</pre>
<p>Notez que l&#8217;interopérabilité entre C# et C++/CLI est native : les deux langages sont managés.</p>
<p>Et en C++ pas CLI, qu&#8217;est-ce que donnent les fonctions à nombre variable d&#8217;arguments ?</p>
<p>Bah c&#8217;est encore plus moche, et plus contraignant. Rappelez-vous :</p>
<pre class="brush: cpp;">
extern &quot;C&quot; __declspec(dllexport) double average(int n, ...)
{
	double sum = 0;
	va_list args;
	va_start(args, n);
	for(int i=0 ;i &lt; n; i++)
		sum += va_arg(args, int);
	va_end(args);
	return sum/n;
}
</pre>
<p>La principale différence est finalement assez subtile on n&#8217;utilise pas explicitement un tableau, mais on fournit un pointeur vers le début de la liste d&#8217;arguments. C&#8217;est à la méthode de se débrouiller (avec des macros) pour itérer, caster et s&#8217;arrêter lorsqu&#8217;il le faut. Généralement, un autre paramètre nommé de la méthode contient les infos nécessaires à cette opération. Dans l&#8217;exemple précédent, &#8220;<code>n</code>&#8221; est utilisé pour passer directement le nombre d&#8217;arguments de la liste. Dans <code>printf</code>, c&#8217;est la <em>format string</em> qui permet à la fonction de savoir combien d&#8217;arguments elle doit lire.</p>
<p>La question rigolote, puisque nous sommes dans le contexte d&#8217;un exemple rigolo, est la suivante :</p>
<p>Mais comment appeler les fonctions natives de ce genre depuis C# ? En utilisant <code><a href="http://fr.wikipedia.org/wiki/P/Invoke">pinvoke</a></code>, probablement, mais plus précisément ?</p>
<p>Réponse : En pleurant. On est obligé de déclarer explicitement les imports pour chacune des utilisations que l&#8217;on va faire de la fonction dans notre code managé. En gros :</p>
<pre class="brush: csharp;">
[DllImport (&quot;NativeLibrary.dll&quot;)]
public static extern double average (int n, int i1);

[DllImport (&quot;NativeLibrary.dll&quot;)]
public static extern double average (int n, int i1, int i2);

[DllImport (&quot;NativeLibrary.dll&quot;)]
public static extern double average (int n, int i1, int i2, int i3);

[DllImport (&quot;NativeLibrary.dll&quot;)]
public static extern double average (int n, int i1, int i2, int i3, int i4);

// Etc.
</pre>
<p>What a <a href="http://www.urbandictionary.com/define.php?term=PITA">PITA</a>, comme qui dirait&#8230; Mais c&#8217;est ici que l&#8217;ornithorynque nous sauve la vie. Car on peut écrire :</p>
<pre class="brush: csharp;">
[DllImport (&quot;NativeLibrary.dll&quot;, CallingConvention = CallingConvention.Cdecl)]
public static extern double average (int n, __arglist );
</pre>
<p>Et appeler la fonction ainsi :</p>
<pre class="brush: csharp;">
NativeWrapper.average (4, __arglist (45, 68, 97, 45))
</pre>
<p>Hourra, donc. Mais quel est ce mot clé bizarre, <code>__arglist</code>, qui n&#8217;est même pas reconnu par Resharper ? Et bien il s&#8217;agit d&#8217;un des mots clés <em>non documentés</em> du langage, qui permettent principalement de jouer avec les <code>TypedReference</code>. Pour mieux comprendre ce qui se passe, essayons de réécrire en C# la méthode <code>Average</code>, sans utiliser le mot clé <code>params</code>, et en se reposant donc uniquement sur les &#8220;références typées&#8221;. On s&#8217;attaquera ensuite à la définition.</p>
<pre class="brush: csharp;">
public class ManagedEvil
{
    public static double Average(__arglist)
    {
        double sum = 0;
        int count = 0;
        var iterator = new ArgIterator(__arglist);
        do
        {
            TypedReference typedReference = iterator.GetNextArg();
            sum += __refvalue( typedReference,int);
            count++;
        } while (iterator.GetRemainingCount() &gt; 0);
        return sum / count;
    }
}
</pre>
<p>On note :</p>
<ul>
<li>L&#8217;apparition du type <code>ArgIterator</code>, dont on crée une instance à partir de la liste d&#8217;arguments.</li>
<li>L&#8217;élément courant retourné par l&#8217;itérateur est une référence typée : <code>TypedReference</code>.</li>
<li>Un nouveau mot clé, <code>__refvalue</code>, permet d&#8217;extraire la valeur pointée par la référence.</li>
</ul>
<p>Et tout ça compile, tout ça fonctionne, même si l&#8217;intérêt est limité. </p>
<h3><code>TypedReference</code>, <code>__makeref</code>, <code>__refvalue</code>, <code>__reftype</code></h3>
<p>Arrêtons les expériences pour décortiquer un peu plus sérieusement ce <code>TypedReference</code>. La MSDN définit <strike>très clairement</strike> la <code>TypedReference</code> :</p>
<blockquote><p>Describes objects that contain both a managed pointer to a location and a runtime representation of the type that may be stored at that location.</p></blockquote>
<p>Retenons qu&#8217;il s&#8217;agit d&#8217;une structure contenant : </p>
<ul>
<li>Un pointeur managé vers un espace mémoire</li>
<li>Le type de ce qui est pointé en mémoire</li>
</ul>
<p>Le meilleur endroit pour trouver des infos au sujet de <code>TypedReference</code> est finalement la spécification <a href="http://www.ecma-international.org/publications/standards/Ecma-335.htm">ECMA 335 du CIL</a>. Je vous laisse fouiller, mais sachez que les bases sont notamment posées dans le paragraphe suivant (cf. 8.6.1.3):</p>
<blockquote><p>La signature d&#8217;une référence typée est en fait représentée en tant que type valeur de base, comme les entiers ou nombres à virgule flottante. Dans la bibliothèque de classes du framework, le type est représenté par <code>System.TypedReference</code>, tandis que dans le langage intermédiaire il est désigné par le mot clé <code>typedref</code>. Ce type doit uniquement être utilisé pour les paramètres et les variables locales. Il ne peut ni être boxé ni être utilisé pour typer un champ, un élément de tableau, ou une valeur de retour de fonction.</p></blockquote>
<p>Pour que je ne puisse jamais justifier l&#8217;intérêt de cet article, les gens chez Microsoft ont bien fait attention à exposer ce type le moins possible. Il est pourtant assez utilisé en interne, notamment dans <code>System.Array</code>, <code>System.Threading.Interlocked</code>, les services d&#8217;intérop (<code>InteropServices</code>) ainsi que dans certains overloads cachés utilisant les varargs (<code>String.Concat</code>, <code>Console.WriteLine</code>). A vrai dire, il semblerait que la raison officielle de son existence soit justement le support par le CLR des listes d&#8217;arguments, comme nous l&#8217;avons vu plus tôt. Il existe cependant un autre endroit (parmi d&#8217;autres) où son utilisation peut s&#8217;avérer intéressante : la réflexion via les <code>FieldInfo</code>. Mais avant d&#8217;y venir, regardons plutôt comment utiliser, très mécaniquement, <code>TypedReference</code>. On peut soit utiliser les mots clés interdits, soit &#8211; lorsque c&#8217;est possible &#8211; utiliser les quelques méthodes statiques de la classe <code>TypedReference</code> elle-même.</p>
<p><strong>Création d&#8217;une référence typée</strong> : <code>__makeref</code></p>
<p>Les références typées peuvent être obtenues pour des variables de n&#8217;importe quel type (référence ou valeur) à l&#8217;aide du mot clé <code>__makeref</code>.</p>
<pre class="brush: csharp;">
int i = 42;
TypedReference typedReference = __makeref (i);
</pre>
<p>Ce mot clé dont l&#8217;usage n&#8217;est pas documenté correspond à l&#8217;instruction <code>mkrefany</code> en CIL. Le code intermédiaire correspondant à l&#8217;exemple précédant est le suivant :</p>
<pre class="brush: cpp;">
int i = 42;

L_0000: ldc.i4.s 0x2a	/* push sur la pile d'un int32 = 42						*/
L_0002: stloc.0			/* sauvegarde dans la variable locale i					*/

TypedReference typedReference = __makeref(i);

L_0003: ldloca.s i		/* push sur la pile de l'adresse de i					*/
L_0005: mkrefany int32	/* push sur la pile de la référence typée				*/
L_000a: stloc.1			/* sauvegarde dans la variable locale typedReference	*/
</pre>
<p>La méthode statique <code>TypedReference.MakeTypedReference</code> permet aussi de créer des références typées, mais pas directement à partir d&#8217;une variable. Nous verrons un exemple d&#8217;utilisation dans la dernière partie de l&#8217;article.</p>
<p><strong>Récupérer et/ou modifier la valeur</strong> : <code>__refvalue</code></p>
<p>Une fois qu&#8217;on a une référence typée, il est possible de lire et/ou d&#8217;écrire la valeur référencée en utilisant le mot clé <code>__refvalue</code>. Il est visuellement assimilable à un appel de fonction à deux paramètres, dont le premier serait la <code>TypedReference</code>, et le second le type de la valeur référencée. En l&#8217;utilisant à droite d&#8217;une affectation, on lit la valeur, et en l&#8217;utilisant à gauche d&#8217;une affectation, on écrit la valeur. Assez troublant&#8230;</p>
<pre class="brush: csharp;">
int i = 42;
TypedReference typedReference = __makeref(i);
int j = __refvalue (typedReference, int);
__refvalue (typedReference, int) = 24;
</pre>
<p>Encore une fois, il est possible de mapper son utilisation avec un opcode spécifique, <code>refanyval</code> :</p>
<pre class="brush: cpp;">
int i = 42;
TypedReference typedReference = __makeref(i);

L_0000: ldc.i4.s 0x2a	/* push sur la pile d'un int32 = 42						*/
L_0002: stloc.0			/* sauvegarde dans la variable locale i					*/
L_0003: ldloca.s i		/* push sur la pile de l'adresse de i					*/
L_0005: mkrefany int32	/* push sur la pile de la référence typée				*/
L_000a: stloc.1			/* sauvegarde dans la variable locale typedReference	*/

int j = __refvalue (typedReference, int);

L_000b: ldloc.1			/* push sur la pile de la typedReference				*/
L_000c: refanyval int32 /* push sur la pile de l'adresse de la référence        */
L_0011: ldind.i4		/* déréférencement et push sur la pile de la valeur		*/
L_0012: stloc.2			/* sauvegarde dans la variable locale j					*/

__refvalue (typedReference, int) = 24;

L_0013: ldloc.1			/* push sur la pile de la typedReference				*/
L_0014: refanyval int32 /* push sur la pile de l'adresse de la référence        */
L_0019: ldc.i4.s 0x18	/* push sur la pile d'un int32 = 24						*/
L_001b: stind.i4		/* sauvegarde de la valeur à l'adresse de la référence  */
</pre>
<p>La méthode <code>TypedReference.ToObject</code> permet aussi de déréférencer la <code>TypedReference</code> et d&#8217;obtenir sa valeur, boxée.</p>
<p><strong>Récupérer le type</strong> : <code>__reftype</code></p>
<p>Enfin, il est possible de récupérer l&#8217;information de type associée à la <code>TypeReference</code>, en utilisant un dernier mot clé <code>__reftype</code>.</p>
<pre class="brush: csharp;">
int i = 42;
TypedReference typedReference = __makeref(i);
Type type = __reftype(typedReference);
</pre>
<p>Là encore, on peut faire correspondre <code>__reftype</code> à l&#8217;opcode <code>refanytype</code> :</p>
<pre class="brush: cpp;">
int i = 42;
TypedReference typedReference = __makeref(i);

L_0000: ldc.i4.s 0x2a	/* push sur la pile d'un int32 = 42						*/
L_0002: stloc.0			/* sauvegarde dans la variable locale i					*/
L_0003: ldloca.s i		/* push sur la pile de l'adresse de i					*/
L_0005: mkrefany int32	/* push sur la pile de la référence typée				*/
L_000a: stloc.1			/* sauvegarde dans la variable locale typedReference	*/

Type type = __reftype(typedReference);

L_000b: ldloc.1			/* push sur la pile de la typedReference				*/
L_000c: refanytype		/* push sur la pile du type token de la référence		*/
L_000e: call class Type::GetTypeFromHandle(RuntimeTypeHandle)
L_0013: stloc.2			/* récupération et sauvegarde du Type à partir du token */
</pre>
<p>Notons que la méthode statique <code>TypedReference.GetTargetType</code> est l&#8217;équivalent autorisé de <code>__reftype</code>, et qu&#8217;il existe aussi la méthode <code>TypedReference.TargetTypeToken</code> qui retourne le handle du type sous la forme d&#8217;un <code>RuntimeTypeHandle</code>. La version light, en somme. </p>
<p>Rien de très impressionnant ; d&#8217;ailleurs vous pouvez retourner sur youtube car la suite n&#8217;est pas mieux. Mais je persiste !</p>
<h3>Un autre exemple : <code>GetValueDirect</code> et <code>SetValueDirect</code></h3>
<p>Je vous disais tout à l&#8217;heure que j&#8217;avais trouvé un exemple d&#8217;utilisation dans lequel on pouvait faire intervenir les <code>TypedReference</code>. Il s&#8217;agit de la lecture écriture des champs par réflexion, et plus particulièrement des champs de type valeur. Et encore plus particulièrement lorsqu&#8217;ils sont imbriqués.</p>
<p>Prenons pour exemple ce modèle simpliste :</p>
<pre class="brush: csharp;">
public struct Person
{
	public Address Address;
}

public struct Address
{
	public City City;
}

public struct City
{
	public int ZipCode;
}
</pre>
<p>Il est important de bien noter que <code>Person</code>, <code>Address</code>, <code>City</code> et <code>ZipCode</code> sont des value types. Si on veut inspecter une instance de <code>Person</code> par réflexion, jusqu&#8217;à lire le <code>ZipCode</code> de son adresse, on va écrire quelque chose comme :</p>
<pre class="brush: csharp;">
// On a une instance de Person
var p = new Person();
p.Address.City.ZipCode = 75000;

// On récupère les FieldInfo
var addressField = typeof(Person).GetField(&quot;Address&quot;);
var cityField = typeof(Address).GetField(&quot;City&quot;);
var zipCodeField = typeof(City).GetField(&quot;ZipCode&quot;);

// On chaine les appels à FieldInfo.GetValue pour inspecter la Person
// et lire la valeur du ZipCode
var zipCode =  (int)zipCodeField.GetValue(cityField.GetValue(addressField.GetValue(p)));
</pre>
<p>Ca fonctionne, mais le boxing a tué mon hourra. <code>GetValue</code> prend un <code>object</code> en argument, et retourne un <code>object</code>, alors qu&#8217;on travaille ici sur des types valeurs&#8230; En lisant la dernière ligne de droite à gauche :</p>
<ul>
<li>p va être boxé pour être passé en paramètre à <code>GetValue</code></li>
<li><code>addressField.GetValue</code> va boxer la valeur du champ <code>Address</code> pour le retourner sous la forme d&#8217;un <code>object</code></li>
<li><code>cityField.GetValue</code> va boxer la valeur du champ <code>City</code> pour le retourner sous la forme d&#8217;un <code>object</code></li>
<li><code>zipCodeField.GetValue</code> va boxer la valeur du champ <code>ZipCode</code> pour le retourner sous la forme d&#8217;un <code>object</code></li>
<li>Le cast en <code>int</code> effectue l&#8217;ultime et nécessaire unboxing</li>
</ul>
<p>Pas terrible&#8230;</p>
<p>Heureusement, il existe sur <code>FieldInfo</code> la méthode <code>GetValueDirect</code>, qui prend en paramètre une <code>TypedReference</code> !</p>
<p>Si on peut directement récupérer une référence typée sur le <code>ZipCode</code>, on peut éviter quelques emboitages :</p>
<pre class="brush: csharp;">
var p = new Person();
p.Address.City.ZipCode = 75000;
FieldInfo zipCodeField = typeof(City).GetField(&quot;ZipCode&quot;);
var zipCode = (int)zipCodeField.GetValueDirect(__makeref (p.Address.City));
</pre>
<p>Seulement, on change les contraintes, car la création de la référence typée de cette façon implique alors que l&#8217;on connaisse <code>Address</code> et <code>City</code> au design time. Qu&#8217;à cela ne tienne : il existe la méthode statique <code>TypedReference.MakeTypedReference</code> évoquée plus tôt, qui permet de construire une référence typée à partir d&#8217;une target et d&#8217;un tableau de <code>FieldInfo</code> correspondant à l&#8217;inspection désirée de l&#8217;espace mémoire réservé par <code>p</code> :</p>
<pre class="brush: csharp;">
var p = new Person ();
p.Address.City.ZipCode = 75000;
var addressField = typeof (Person).GetField (&quot;Address&quot;);
var cityField = typeof (Address).GetField (&quot;City&quot;);
var zipCodeField = typeof (City).GetField (&quot;ZipCode&quot;);

TypedReference r = TypedReference.MakeTypedReference (p, new[] {addressField, cityField});
var zipCode = (int) zipCodeField.GetValueDirect (r);
</pre>
<p>Dans ce cas précis, les performances mesurées sont environ <strong>4 fois meilleures</strong> en utilisant <code>GetValueDirect</code> à la place de <code>GetValue</code>. Hourra.</p>
<p>Quant à l&#8217;écriture, nous n&#8217;avons même pas le luxe du choix, puisque chainer les <code>SetValue</code> ne peut en aucun cas modifier la personne, cette fonction retournant à chaque fois une <em>copie</em> des valeurs&#8230; Il faut donc nécessairement utiliser <code>SetValueDirect</code> et une <code>TypedReference</code>.</p>
<h3>Conclusion</h3>
<p>La conclusion, que je vous dois brève :</p>
<p><strong>Ce qui n&#8217;est pas documenté ne doit pas être utilisé</strong>. En gros, tout ce qui est lié aux arglists est à oublier. En revanche, la création et la manipulation de <code>TypedReference</code> sans passer par tous les __mots __clés __moches n&#8217;est pas réprouvée. Notez simplement que <code>TypedReference</code> n&#8217;est pas <em>CLS Compliant</em>.</p>
Posted in Articles Tagged: .NET, C#, CIL, Optimisation <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/romainverdier.wordpress.com/535/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/romainverdier.wordpress.com/535/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/romainverdier.wordpress.com/535/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/romainverdier.wordpress.com/535/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/romainverdier.wordpress.com/535/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/romainverdier.wordpress.com/535/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/romainverdier.wordpress.com/535/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/romainverdier.wordpress.com/535/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/romainverdier.wordpress.com/535/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/romainverdier.wordpress.com/535/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=535&subd=romainverdier&ref=&feed=1" /></div><img src="http://feeds.feedburner.com/~r/Codingly/~4/-1ImBKH4ikg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codingly.com/2009/01/15/si-les-types-etaient-des-animaux-typedreference-serait-un-ornithorynque/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb0ee4bde49708f4be24a02a5d59e52e?s=96&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">Romain</media:title>
		</media:content>
	<feedburner:origLink>http://codingly.com/2009/01/15/si-les-types-etaient-des-animaux-typedreference-serait-un-ornithorynque/</feedburner:origLink></item>
		<item>
		<title>Dégage, sale programmeur !</title>
		<link>http://feedproxy.google.com/~r/Codingly/~3/UawqGs3KAtg/</link>
		<comments>http://codingly.com/2008/12/29/degage-sale-programmeur/#comments</comments>
		<pubDate>Mon, 29 Dec 2008 23:35:29 +0000</pubDate>
		<dc:creator>Romain Verdier</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[Opinion]]></category>

		<guid isPermaLink="false">http://codingly.com/?p=491</guid>
		<description><![CDATA[Et ouais, être développeur lorsqu&#8217;on a plus de 30 ans en France, c&#8217;est pire que d&#8217;être caissier à 40 ans. La plupart des gens qui passent 90% de leur temps à programmer vont s&#8217;arranger pour qu&#8217;on les voit comme des ingénieurs d&#8217;études, des experts techniques, des chefs de projets, des architectes solution, des consultants, etc. [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=491&subd=romainverdier&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Et ouais, être développeur lorsqu&#8217;on a plus de 30 ans en France, c&#8217;est pire que d&#8217;être caissier à 40 ans. La plupart des gens qui passent 90% de leur temps à programmer vont s&#8217;arranger pour qu&#8217;on les voit comme des ingénieurs d&#8217;études, des experts techniques, des chefs de projets, des architectes solution, des consultants, etc. Le top, quand on est un pauvre prestataire d&#8217;une SSII en mission pour une banque, et que l&#8217;on passe ses journées à coder, c&#8217;est de raconter à tout le monde qu&#8217;on est INGENIEUR DANS LA FINANCE. Oui oui.</p>
<p>C&#8217;est assez terrible, mais il semblerait qu&#8217;on n&#8217;y puisse pas grand chose.</p>
<p><span id="more-491"></span></p>
<p>La première observation, c&#8217;est que le phénomène est assez localisé. Ou plutôt : le phénomène n&#8217;est pas généralisé. En France, dès les études, on explique qu&#8217;il y a les développeurs (berk), et les chefs (ouais).</p>
<blockquote><p>Bon, les enfants, si vous avez été admis chez SUPIMAG, c&#8217;est pas pour finir développeur. En sortant de notre établissement, espérez être chef de projet junior (à la tête de 5 développeurs, 52K€, pendant 6 à 12 mois), puis, <em>évidemment</em> directeur de projet (1200 développeurs à vos pieds, 420K€ + iPhone + bonus)</p></blockquote>
<p>Et ensuite, même si on se fout de votre gueule lors des premiers entretiens, c&#8217;est trop tard : vous ne voulez plus, vous ne pouvez plus être développeur. On pourrait vous confondre avec l&#8217;admin réseau (BTS Informatique et Réseaux pour l’Industrie et les Services Techniques, 23K€, Nokia 3310 pour les astreintes). </p>
<p>Aux Etats-Unis, par exemple, et sans doute ailleurs, ça ne fonctionne pas comme ça. Il y a <a href="http://stackoverflow.com/questions/389833/manager-versus-developer-as-a-career">différents métiers</a>. Développeur, c&#8217;est un métier. Manager, c&#8217;est un <em>autre métier</em>. Le développeur programme, et le manager gère. Il est tout à fait possible de rester programmeur lorsqu&#8217;on devient papa. On n&#8217;est pas pris pour un con, juste pour un programmeur senior, payé et reconnu comme tel. Un professionnel ayant fait un choix de carrière plutôt qu&#8217;un autre, en somme. Il n&#8217;y a pas une hiérarchie dans laquelle le programmeur est en bas de l&#8217;échelle, il y a juste différents métiers dont les exercices sont nécessaires à la réalisation des projets informatiques.</p>
<p>Tant qu&#8217;on ne comprendra pas ça ici, on continuera à subir les rires bruyants des gros blaireaux qui parlent de pissage-de-code-lol.</p>
<p>Gens, vous vous trompez.</p>
<p>Le développement, ou l&#8217;ingénierie logicielle si on veut élargir un peu, est une discipline <em>complexe</em>, qui requiert un cerveau. Un développeur digne de ce nom est une personne capable de réfléchir, de conceptualiser, de comprendre. C&#8217;est une personne capable de travailler en équipe, de communiquer efficacement, de s&#8217;organiser. C&#8217;est une personne qui ne peut pas se reposer éternellement sur ses acquis. C&#8217;est aussi une personne qui doit produire, et qui peut difficilement tricher. Programmer est un métier à la fois compliqué et passionnant, dont on peut même penser qu&#8217;il demande du talent. En fait, c&#8217;est probablement l&#8217;un des métiers les plus exigeants et intelligents qui soient.</p>
<p>Il est presque incompréhensible qu&#8217;on en soit arrivé à trouver ça péjoratif, et que la programmation ait été reléguée au rang de tâche honteuse. </p>
<blockquote><p><strong>Programmeur</strong> : n.m. Celui dont le métier est de rédiger des programmes informatiques. Le plus souvent, jeune diplômé, ou chef de projet raté. Syn. <em>loser</em>. Ex. <em>Tu crains comme un programmeur</em>.</p></blockquote>
<p>Première hypothèse : Romain, t&#8217;es un crétin doublé d&#8217;un parano : personne n&#8217;a cette sale image des développeurs. Deuxième hypothèse &#8211; très personnelle et probablement très discutable : tout le monde n&#8217;est pas né pour être programmeur. Et tant mieux, devrais-je ajouter : il serait assez triste de rêver du contraire. Cependant, il y a un besoin de programmeurs, en France comme ailleurs, et donc, on obtient fatalement une armée de développeurs-malgré-eux. Ni particulièrement doués ni particulièrement motivés, il se retrouvent à devoir maintenir des applications plus ou moins monstrueuses, sans vraiment comprendre ce qu&#8217;ils font et sans avoir envie d&#8217;ailleurs d&#8217;en comprendre plus. Développer, pfiou, c&#8217;est finalement un peu relou, hein. Vivement que je puisse moi aussi passer mes journées sur Powerpoint.</p>
<p>Ce que je veux dire, c&#8217;est que dans le fond, il y a peu de personnes qui savent ce qu&#8217;est la programmation. Parmi les programmeurs, les chefs, les recruteurs, les profs, les chats, ma mère. Moi, plus par fausse modestie que pour paraphraser Socrate, j&#8217;ai découvert il n&#8217;y a pas si longtemps que je ne savais pas vraiment ce qu&#8217;était la programmation.</p>
<p>Bon, j&#8217;exagère un peu pour que vous souriez, mais au delà de la simplification volontairement naïve et de la provocation facile, je crois qu&#8217;il y a un peu de vrai. Quand la Masse se met d&#8217;accord sur une définition faussée du métier de programmeur, les choses sont vite réglées. A côté de ça, il y a des développeurs &#8220;qui ont goûté au sang&#8221; (© <a href="http://evain.net/blog/">Jb</a>) et qui ont du mal à revenir aux <a href="http://admin.proxi-business.com/uploads/CHAMPION_GRANDCHAMP/PHOTO1/3033490/281021.jpg">Taillefine &#8220;Pruneau&#8221; 0%</a>. Tant qu&#8217;à faire, ne confondez pas tout le monde et choisissez bien votre audience le jour où vous voulez expliquer que vous aimez programmer, ou pire, que vous êtes capable d&#8217;en tirer une certaine fierté.</p>
<p>Au fait, ça existe les architectes qui écrivent juste les prototypes des méthodes et qui laissent l&#8217;implémentation aux programmeurs ?</p>
Posted in Posts Tagged: Opinion <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/romainverdier.wordpress.com/491/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/romainverdier.wordpress.com/491/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/romainverdier.wordpress.com/491/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/romainverdier.wordpress.com/491/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/romainverdier.wordpress.com/491/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/romainverdier.wordpress.com/491/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/romainverdier.wordpress.com/491/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/romainverdier.wordpress.com/491/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/romainverdier.wordpress.com/491/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/romainverdier.wordpress.com/491/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=491&subd=romainverdier&ref=&feed=1" /></div><img src="http://feeds.feedburner.com/~r/Codingly/~4/UawqGs3KAtg" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codingly.com/2008/12/29/degage-sale-programmeur/feed/</wfw:commentRss>
		<slash:comments>112</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb0ee4bde49708f4be24a02a5d59e52e?s=96&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">Romain</media:title>
		</media:content>
	<feedburner:origLink>http://codingly.com/2008/12/29/degage-sale-programmeur/</feedburner:origLink></item>
		<item>
		<title>Cecil.Decompiler : Un décompilateur .NET OpenSource</title>
		<link>http://feedproxy.google.com/~r/Codingly/~3/ZOGtdt8U7nA/</link>
		<comments>http://codingly.com/2008/12/16/cecildecompiler-un-decompilateur-net-opensource/#comments</comments>
		<pubDate>Tue, 16 Dec 2008 22:23:30 +0000</pubDate>
		<dc:creator>Romain Verdier</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[.NET]]></category>
		<category><![CDATA[Annonce]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[Cecil.Decompiler]]></category>
		<category><![CDATA[Expression Tree]]></category>

		<guid isPermaLink="false">http://codingly.com/?p=450</guid>
		<description><![CDATA[Jean-Baptiste Evain vient de l&#8217;annoncer sur son blog : il travaille actuellement sur un nouveau projet particulièrement ambitieux appelé Cecil.Decompiler. Comme son nom l&#8217;indique, il s&#8217;agit d&#8217;un décompilateur .NET basé sur Mono.Cecil (du même auteur) qui permettait déjà de manipuler le langage intermédiaire du CLR.
Quelques jours avant l&#8217;annonce officielle, Jb a organisé un Code Camp [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=450&subd=romainverdier&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p>Jean-Baptiste Evain <a href="http://evain.net/blog/articles/2008/12/15/cecil-decompiler">vient de l&#8217;annoncer</a> sur son blog : il travaille actuellement sur un nouveau projet particulièrement ambitieux appelé Cecil.Decompiler. Comme son nom l&#8217;indique, il s&#8217;agit d&#8217;un décompilateur .NET basé sur <a href="http://www.mono-project.com/Cecil">Mono.Cecil</a> (du même auteur) qui permettait déjà de manipuler le langage intermédiaire du CLR.</p>
<p>Quelques jours avant l&#8217;annonce officielle, Jb a organisé un <a href="http://evain.net/blog/articles/2008/12/16/decompiler-codecamp">Code Camp</a> en Ardèche (près de Lyon) en invitant quelques personnes à travailler avec lui sur ce decompiler. L&#8217;idée était avant tout de passer un bon moment, de <strike>faire avancer</strike> découvrir le projet, mais aussi d&#8217;intéresser et d&#8217;encourager d&#8217;éventuels futurs contributeurs à rejoindre l&#8217;initiative.</p>
<p>Comme j&#8217;ai eu la chance de faire partie des petits privilégiés, je vais essayer de vous livrer mes impressions à chaud.<br />
<span id="more-450"></span><br />
Déjà, belle surprise en recevant le mail d&#8217;invitation de Jb&#8230; Nous ne nous étions croisé qu&#8217;une soirée, à Paris, lorsqu&#8217;il était <a href="http://codingly.com/2008/11/05/altnet-en-france-mono-a-paris-pour-la-7eme-rencontre/">venu présenter Mono</a> en novembre pour une de nos réunions ALT.NET. Dans un milieu où le copinage reste bien présent, ce genre de proposition dénote bien une certaine ouverture d&#8217;esprit, et un fort degré de coolitude. Merci. <a href="http://strangelights.com/blog/">Robert Pickering</a> faisait aussi partie des invités mais à part lui (et Jb, donc) je ne connaissais personne. Ce fut l&#8217;occasion de faire la connaissance de <a href="http://patricelamarche.net/">Patrice Lamarche</a>, <a href="http://batswirl.com/">Mathieu Szablowski</a>, <a href="http://evilznet.com/">Vincent Bourdon</a>, et <a href="http://sebastien.lebreton.free.fr/blog/">Sébastien Lebreton</a> (auteur de réflexil). Sept personnes en tout ; soit un petit comité.</p>
<p><img src="http://romainverdier.files.wordpress.com/2008/12/codecamp2.jpg?w=715&#038;h=405" alt="codecamp2" title="codecamp2" width="715" height="405" class="alignnone size-full wp-image-462" /></p>
<p>Je vous avouerai que j&#8217;étais un peu impressionné à l&#8217;idée de devoir rejoindre tout ce beau monde pour travailler sur un projet de cette envergure, dont la complexité moyenne dépasse quand même celle d&#8217;une application de gestion classique&#8230; Mais l&#8217;ambiance était excellente d&#8217;une part, et le sujet carrément intéressant d&#8217;autre part.</p>
<p>Ca ne suffit pas pour faire oublier qu&#8217;on est en train de faire du pair programming avec un mec de l&#8217;équipe Mono, mais ça aide un peu. En tout cas, ça fait vraiment plaisir de participer à un projet aussi motivant, avec des gens dont la simple proximité rend moins con. J&#8217;aurais aimé pouvoir travailler en pair avec tout le monde, mais j&#8217;ai principalement codé avec Jb et Rob. Et tout seul aussi, hein. Je n&#8217;ai pas envie de rentrer dans les détails techniques aujourd&#8217;hui, mais en gros, j&#8217;ai principalement travaillé sur la partie &#8220;décompilation C#&#8221;, et plus particulièrement sur les étapes de transformation de l&#8217;arbre syntaxique visant à faire apparaitre les structures de haut niveau du langage.</p>
<p>Le decompiler lit le code intermédiaire, en infère un <a href="http://en.wikipedia.org/wiki/Control_flow_graph">Control Flow Graph</a>, puis un <a href="http://en.wikipedia.org/wiki/Abstract_syntax_tree">AST</a> assez brut dans lequel, par exemple, toutes les pre/post-tested loops sont modélisées sous la forme de statements while/do-while. Selon le langage, et selon la version du langage, il faudra ensuite exécuter une série d&#8217;analyses et de transformations sur cet arbre afin de reconnaitre les constructions spécifiques. Par exemple, et <em>au hasard</em>, le foreach.</p>
<p>Dans un <a href="http://codingly.com/2008/04/28/le-mot-cle-yield-et-les-iterateurs-en-c/">vieux post</a>, j&#8217;expliquais que le foreach en C# était syntaxiquement équivalent à :</p>
<pre class="brush: csharp;">
IEnumerator&lt;Jambon&gt; enumerator = jambons.GetEnumerator();
try
{
	while( enumerator.MoveNext())
	{
		Jambon jambon = enumerator.Current;
		// Manger le jambon, miam, etc.
	}
}
finally
{
	IDisposable disposableEnumerator = enumerator as IDisposable;
	if(disposableEnumerator != null)
	{
		disposableEnumerator.Dispose();
	}
}
</pre>
<p>C&#8217;est donc le pattern qu&#8217;il faut identifier dans l&#8217;arbre, à quelques subtilités près. Ca m&#8217;a pris 3 bons jours, et c&#8217;est loin d&#8217;être terminé si on veut gérer tous les edge cases, allez donc savoir pourquoi. J&#8217;ai aussi travaillé avec Jb sur une implémentation sympa d&#8217;un &#8220;pattern matching du pauvre&#8221; en C#, joyeusement supprimée depuis&#8230; On cherche quelque chose de mieux. Mais ça permettait d&#8217;écrire des trucs rigolos du genre :</p>
<pre class="brush: csharp;">
// Création du pattern
var matcher = Pattern.Match&lt;Expression&gt;()
					 .Is&lt;MethodInvocationExpression&gt;()
                     .Select(mie =&gt; mie.Method)
                     .Is&lt;MethodReferenceExpression&gt;()
                     .Tag(() =&gt; method_key, mre =&gt; mre.Method)
                     .Tag(() =&gt; target_key, mre =&gt; mre.Target);

// Compilation du pattern matcher pour récupérer un delegate qui pourra être mis en cache
// et invoqué avec de bonnes performances
var methodInvocationMatcher = matcher.Compile&lt;Func&lt;MatchResult, Expression, bool&gt;&gt; ();

// Exécution du pattern matching : on obtient un MatchResult
var result = Pattern.Run (MethodInvocationMatcher, expression);

// On peut maintenant, en cas de succès, travailler avec les valeurs qui ont été tagguée
// lors du pattern matching, si elles ont été trouvées
if (result.Success)
{
	Expression targetExpression;
    if (result.TryGetValue(target_key, out targetExpression))
    {
		// ...
	}

	MethodReference methodReference;
	if (result.TryGetValue(method_key, out methodReference))
	{
		// ...
	}
}
</pre>
<p>Le code du matcher pouvait être généré dynamiquement via <code>System.Reflection.Emit</code>, puis compilé pour obtenir un delegate capable d&#8217;être exécuté sans ruiner les perfs. Ca peut <a href="http://codingly.com/2008/05/06/continuer-loptimisation-avec-la-lightweight-code-generation-lcg/">vous rappeler quelque chose</a>&#8230; mais l&#8217;idée n&#8217;était pas de moi !</p>
<p>J&#8217;ai également eu l&#8217;opportunité de travailler avec Rob pour réaliser une version F# du matcher capable de détecter les foreach à titre d&#8217;essai. Pas vraiment l&#8217;initiation idéale à F# pour un profane comme moi, mais heureusement Rob a gardé le clavier durant la session. Ce fut pour moi l&#8217;occasion d&#8217;avoir un bon aperçu de la puissance du langage en matière de pattern matching et de tester rapidement pour la première fois l&#8217;intérop C#/F#.</p>
<p><img src="http://romainverdier.files.wordpress.com/2008/12/codecamp1.jpg?w=358&#038;h=246" alt="codecamp1" title="codecamp1" width="358" height="246" class="alignright size-full wp-image-463" /><br />
Le projet en lui-même est à mon sens prometteur. Ce n&#8217;est pas juste un Reflector-bis. Il s&#8217;agit d&#8217;un framework de décompilation, libre et open source, qui peut être embarqué n&#8217;importe où. Ca ouvre pas mal de perspectives pour ceux qui travaillent sur des outils d&#8217;analyse statique de code par exemple. Jason Bock, auteur de CIL Programming avec lequel j&#8217;ai été méchant par le passé, va même jusqu&#8217;à trouver <a href="http://www.jasonbock.net/JB/Default.aspx?blog=entry.850a91e9249c4d388f1ca4a3e64dfed4">Cecil.Decompiler et sa licence MIT/X11 rassurants</a> dans la mesure où la visibilité sur le devenir de Reflector est compromise.</p>
<p>Je ne suis pas sûr de vouloir crier hourra pour ça, mais ce dont je suis sûr, c&#8217;est que pouvoir disposer d&#8217;un décompilateur .NET open source, managé, qui repose sur une base solide, c&#8217;est tout bon. Si on considère en plus que Sébastien est déjà lancé à fond sur la réalisation d&#8217;une interface pour exploiter Cecil.Decompiler, dont le modèle d&#8217;extensibilité devrait être plus souple que celui de Reflector, c&#8217;est encore plus alléchant.</p>
<p>Quoi qu&#8217;il en soit, le decompiler en est à ses débuts. Il reste vraiment beaucoup de choses à faire, et ce à plusieurs niveaux :</p>
<ul>
<li>Core</li>
<li>Support des langages : C#, VB, F#, etc.</li>
<li>Interface, plugins</li>
</ul>
<p>Mais au moins, vous savez à présent que le projet existe.</p>
Posted in Posts Tagged: .NET, Annonce, C#, Cecil.Decompiler, Expression Tree <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/romainverdier.wordpress.com/450/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/romainverdier.wordpress.com/450/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/romainverdier.wordpress.com/450/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/romainverdier.wordpress.com/450/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/romainverdier.wordpress.com/450/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/romainverdier.wordpress.com/450/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/romainverdier.wordpress.com/450/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/romainverdier.wordpress.com/450/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/romainverdier.wordpress.com/450/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/romainverdier.wordpress.com/450/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=codingly.com&blog=3510695&post=450&subd=romainverdier&ref=&feed=1" /></div><img src="http://feeds.feedburner.com/~r/Codingly/~4/ZOGtdt8U7nA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://codingly.com/2008/12/16/cecildecompiler-un-decompilateur-net-opensource/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/cb0ee4bde49708f4be24a02a5d59e52e?s=96&amp;d=http%3A%2F%2F0.gravatar.com%2Favatar%2Fad516503a11cd5ca435acc9bb6523536%3Fs%3D96" medium="image">
			<media:title type="html">Romain</media:title>
		</media:content>

		<media:content url="http://romainverdier.files.wordpress.com/2008/12/codecamp2.jpg" medium="image">
			<media:title type="html">codecamp2</media:title>
		</media:content>

		<media:content url="http://romainverdier.files.wordpress.com/2008/12/codecamp1.jpg" medium="image">
			<media:title type="html">codecamp1</media:title>
		</media:content>
	<feedburner:origLink>http://codingly.com/2008/12/16/cecildecompiler-un-decompilateur-net-opensource/</feedburner:origLink></item>
	</channel>
</rss>
