<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>Pascal Lacroix &#187; .NET</title>
	<atom:link href="http://www.pascallacroix.net/blog/tag/net/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.pascallacroix.net/blog</link>
	<description>Consultant entrepreneur en nouvelles technologies</description>
	<lastBuildDate>Wed, 28 Dec 2011 17:53:04 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0</generator>
		<item>
		<title>Pourquoi le ribbon JobsDotnet?</title>
		<link>http://www.pascallacroix.net/blog/2008/05/29/pourquoi-le-ribbon-jobsdotnet/</link>
		<comments>http://www.pascallacroix.net/blog/2008/05/29/pourquoi-le-ribbon-jobsdotnet/#comments</comments>
		<pubDate>Thu, 29 May 2008 20:22:04 +0000</pubDate>
		<dc:creator>Pascal Lacroix</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[emploi]]></category>
		<category><![CDATA[jobsdotnet]]></category>
		<category><![CDATA[offres d'emploi]]></category>

		<guid isPermaLink="false">http://www.pascallacroix.net/blog/2008/05/29/pourquoi-le-ribbon-jobsdotnet/</guid>
		<description><![CDATA[Vous avez surement remarqué le ribbon JobsDotnet présent sur ce blog dans le coin en haut à droite. Il s&#8217;agit bien d&#8217;une petite publicité dans un nouveau format que je teste. Cette publicité est destinée à un site que j&#8217;ai lancé il y a quelques semaines (j&#8217;en parlerai plus longuement dans quelques jours). Pour avoir [...]]]></description>
			<content:encoded><![CDATA[<p>Vous avez surement remarqué le <strong>ribbon JobsDotnet</strong> présent sur ce blog dans le coin en haut à droite.</p>
<p>Il s&#8217;agit bien d&#8217;une petite publicité dans un nouveau format que je teste. Cette publicité est destinée à un site que j&#8217;ai lancé il y a quelques semaines (j&#8217;en parlerai plus longuement dans quelques jours).</p>
<p>Pour avoir un aperçu et des infos sur le site, rendez-vous sur <a href="http://www.jobsdotnet.com" target="_blank">JobsDotnet :: Offres d&#8217;emploi .NET</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.pascallacroix.net/blog/2008/05/29/pourquoi-le-ribbon-jobsdotnet/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Popfly va-t-il tuer les développeurs?</title>
		<link>http://www.pascallacroix.net/blog/2007/10/19/popfly-va-t-il-tuer-les-developpeurs/</link>
		<comments>http://www.pascallacroix.net/blog/2007/10/19/popfly-va-t-il-tuer-les-developpeurs/#comments</comments>
		<pubDate>Fri, 19 Oct 2007 08:12:42 +0000</pubDate>
		<dc:creator>Pascal Lacroix</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[développement]]></category>
		<category><![CDATA[mashup]]></category>
		<category><![CDATA[silverlight]]></category>

		<guid isPermaLink="false">http://www.pascallacroix.net/wordpress/?p=70</guid>
		<description><![CDATA[<p>Derrière ce titre un peu choc se cache un outil vraiment révolutionnaire. Microsoft sort un nouveau produit qui risque bien de faciliter en davantage le développement d'applications riches.</p>]]></description>
			<content:encoded><![CDATA[<p>Derrière ce titre un peu choc se cache un outil vraiment révolutionnaire. Microsoft sort un nouveau produit qui risque bien de faciliter en davantage le développement d&#8217;applications riches.</p>
<p><span id="more-70"></span></p>
<p><a href="http://www.popfly.com">Popfly</a>est le dernier né des éditeurs de mashus pour Silverlight. <a href="http://www.silverlight.net">Silverlight</a>, comme vous le savez peut être, est un plugin pour les navigateurs internet qui est la réponse à Adobe Flash. Microsoft veut répliquer face à Flash et <a href="http://www.silverlight.net">Silverlight</a> risque bien de faire peur à Adobe car il apporte des éléments très convaincants (dont le support du codec vidéo VC-1 qui semble encore meilleur que le H264 pour de la vidéo HD en plein écran).</p>
<p>Bon revenons à <a href="http://www.popfly.com">Popfly</a>. Il s&#8217;agit donc d&#8217;un mashup creator. Un mashup est une application créée à partir d&#8217;un mélange de services (en général des services web). <a href="http://www.popfly.com">Popfly</a>permet donc de gérer les connexions entre ces services et de créer des applications pour <a href="http://www.silverlight.net">Silverlight</a>.</p>
<p>L&#8217;avantage de <a href="http://www.popfly.com">Popfly</a>, par rapport à un atelier logiciel, est qu&#8217;il est entièrement visuel: on prend un bloc fonctionnel, on le pose, on en prend un second et on crée une connexion entre les deux. L&#8217;utilisation est simple et accessible à n&#8217;importe quelle personne quasiment: plus besoin d&#8217;être développeur pour créer une application. Voici donc la nouvelle attaque de Microsoft!</p>
<p>Bien sûr, <a href="http://www.popfly.com">Popfly</a> ne va pas mettre tous les développeurs au chômage, bien loin de là! En effet, le logiciel propose quelques blocs par défaut. Ces blocs fournissent des fonctions de base: recherche d&#8217;images, modules de sortie, gestion de flux RSS&#8230; Les développeurs seront chargés de créer des blocs personnalisés pouvant réaliser des fonctionnalités complètement différentes. <a href="http://www.popfly.com">Popfly</a>propose les briques de bases pour créer une application <a href="http://www.silverlight.net">Silverlight</a> rapidement.</p>
<p>Je vous invite à essayer <a href="http://www.popfly.com">Popfly</a> et à me laisse vos commentaires sur le produit. Pour essayer, il suffit d&#8217;avoir un compte Live ID et de vous rendre à l&#8217;adresse du projet: <a href="http://www.popfly.com">www.popfly.com</a>.</p>
<p>Vous pouvez également consulter d&#8217;autres articles sur le même sujet:</p>
<ul>
<li><a href="http://www.clubic.com/actualite-73948-popfly-editeur-mashups-microsoft.html" hreflang="fr">http://www.clubic.com/actualite-73948&#8230;microsoft.html</a></li>
<li><a href="http://www.laboratoire-microsoft.org/news-25564-microsoft-popfly-developpement-facile.html" hreflang="fr">http://www.laboratoire-microsoft.org/&#8230;-facile.html</a></li>
<li><a href="http://www.pcinpact.com/actu/news/36487-popfly-microsoft-silverlight-alpha-invitatio.htm" hreflang="fr">http://www.pcinpact.com/actu/news/36487&#8230;invitatio.htm</a></li>
<li><a href="http://fr.techcrunch.com/2007/10/19/microsoft-lance-popfly-la-creation-dapplications-pour-tous/" hreflang="fr">http://fr.techcrunch.com/2007/10/&#8230;pour-tous/</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.pascallacroix.net/blog/2007/10/19/popfly-va-t-il-tuer-les-developpeurs/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Introduction aux itérateurs</title>
		<link>http://www.pascallacroix.net/blog/2006/10/25/introduction-aux-iterateurs/</link>
		<comments>http://www.pascallacroix.net/blog/2006/10/25/introduction-aux-iterateurs/#comments</comments>
		<pubDate>Wed, 25 Oct 2006 11:37:42 +0000</pubDate>
		<dc:creator>Pascal Lacroix</dc:creator>
				<category><![CDATA[.NET]]></category>
		<category><![CDATA[C#]]></category>
		<category><![CDATA[développement]]></category>
		<category><![CDATA[itérateur]]></category>
		<category><![CDATA[pattern]]></category>

		<guid isPermaLink="false">http://www.pascallacroix.net/wordpress/?p=55</guid>
		<description><![CDATA[<p>Cet article présente les itérateurs tels qu'ils sont définis dans le framework 1.0/1.1 et 2.0. Il propose tout d'abord une présentation de l'implémentation dans le framework 1.0, présente ensuite les nouveautés dans la version 2.0 et donne finalement quelques exemples d'utilisations bien pratiques.</p>]]></description>
			<content:encoded><![CDATA[<p>Cet article présente les itérateurs tels qu&#8217;ils sont définis dans le framework 1.0/1.1 et 2.0. Il propose tout d&#8217;abord une présentation de l&#8217;implémentation dans le framework 1.0, présente ensuite les nouveautés dans la version 2.0 et donne finalement quelques exemples d&#8217;utilisations bien pratiques.</p>
<p><span id="more-55"></span></p>
<h3>Définition d&#8217;un itérateur</h3>
<p>Un itérateur est un design pattern utilisé couramment dans les langages objets de haut niveau comme Java ou C#. Il permet de parcourir une liste d&#8217;éléments de manière ordonnée dans avoir à se soucier de la manière dont sont stockés les éléments. C&#8217;est un design pattern de comportement qui permet de parcourir de manière unique une collection d&#8217;objet. Pour plus d&#8217;informations sur les designs pattern en général, je vous invite à consulter l&#8217;excellent article trouvé sur Wikipédia: <a href="http://fr.wikipedia.org/wiki/Design_pattern" hreflang="fr">Design Pattern</a>, <a href="http://fr.wikipedia.org/wiki/It%C3%A9rateur_%28motif_de_conception%29" hreflang="fr">Iterateur</a></p>
<h3>Fonctionnement des itérateurs dans .NET 1.0/1.1</h3>
<h4>Utilisation d&#8217;un itérateur</h4>
<p>Vous avez peut être déjà utilisé des itérateurs dans .NET sans le savoir. Microsoft a développé un ensemble de classes dont beaucoup sont utilisables comme des itérateurs. En réalité, il est possible d&#8217;itérer sur un objet dès le moment qu&#8217;il implémente l&#8217;interface IEnumerable.</p>
<p>Beaucoup de collections, listes, tables de hashages implémentent cette interface. Grâce à cela, il est possible d&#8217;utiliser l&#8217;opérateur foreach de C# pour itérer sur une collection d&#8217;objet.</p>
<p>Voici un exemple très simple:</p>
<pre class="brush: csharp; title: ; notranslate">
ArrayList liste = new ArrayList();
liste.Add(&amp;quot;hello&amp;quot;);
liste.Add(&amp;quot;bonjour&amp;quot;);
liste.Add(&amp;quot;au revoir&amp;quot;);
liste.Add(&amp;quot;bye&amp;quot;);

foreach (string element in liste)
{
    Console.WriteLine(element);
}
</pre>
<p>Cet exemple affiche ceci sur la sortie console:</p>
<pre>
hello
bonjour
au revoir
bye
</pre>
<p>Rien d&#8217;extraordinaire c&#8217;est vrai mais nous avons tout de même réussi à parcourir une liste de manière très simple. Ce fonctionnement est utilisable pour n&#8217;importe quel type d&#8217;objet tant que le conteneur implémente IEnumerable.</p>
<h4>Implémentation</h4>
<p>L&#8217;interface IEnumerable contient la méthode suivante:</p>
<pre class="brush: csharp; title: ; notranslate">
IEnumerator GetEnumerator()
</pre>
<p>Cette méthode doit retourner une instance de type IEnumerator. Cette interface contient les méthodes suivantes:</p>
<pre class="brush: csharp; title: ; notranslate">
object Current { get; }
bool MoveNext()
void Reset()
</pre>
<p>La propriété Current retourne l&#8217;élément courant de la collection. La méthode MoveNext permet de passer à l&#8217;élément suivant. Elle retourne false quand la collection est arrivée à la fin. La méthode Reset permet de réinitialiser la collection pour retourner sur le premier élément.</p>
<h4>Exemple simple</h4>
<p>Voyons de plus près comment créer un itérateur simple. Dans mon exemple, j&#8217;utilise comme nom de classe OldIterator, en référence aux itérateurs de .NET 1.0/1.1. Les itérateurs de .NET 2.0 fonctionnent un peu différemment. (Le code source est proposé à la fin de cette partie)</p>
<h5>Première étape: créer une classe qui implémente IEnumerable</h5>
<pre class="brush: csharp; title: ; notranslate">
class OldIterator: IEnumerable
{
    private string[] m_Values = { &amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;, &amp;quot;d&amp;quot; };
#region IEnumerable Members
    public IEnumerator GetEnumerator()
    {
        return new OldIteratorEnumerator(this);
    }
  #endregion
}
</pre>
<p>Cet exemple présente deux parties: un liste d&#8217;éléments fixe qui contient nos valeurs et la méthode GetEnumerator qui permet d&#8217;utiliser cette classe avec foreach.</p>
<h5>Deuxième étape: créer une classe qui implémente IEnumerator</h5>
<p>Une pratique courante est d&#8217;inclure la classe énumerateur dans la classe IEnumerable. Ceci permet de partager facilement les données de deux classes (la sous-classe aura accès aux membres de la classe parente). Il suffit donc d&#8217;ajouter le code suivant dans la classe OldIterator:</p>
<pre class="brush: csharp; title: ; notranslate">
internal class OldIteratorEnumerator: IEnumerator
{
    private OldIterator m_Parent;
    private int m_Index;
    public OldIteratorEnumerator(OldIterator parent)
    {
        m_Parent    = parent;
        m_Index     = -1;
    }
    #region IEnumerator Members
    /// &amp;lt;summary&amp;gt;
    /// Retourne l'objet courant.
    /// &amp;lt;/summary&amp;gt;
    public object Current
    {
         get
         {
             Console.WriteLine(&amp;quot;### Appel de Current&amp;quot;);
             if (m_Index &amp;amp;lt; 0)
                throw new ApplicationException(&amp;quot;L'index n'a pas encore été initialisé. Il faut appeler la méthode MoveNext en premier.&amp;quot;);
             return m_Parent.m_Values[m_Index];
         }
    }
    /// &amp;lt;summary&amp;gt;
    /// Passer à l'élément suivant.
    /// &amp;lt;/summary&amp;gt;
    /// &amp;lt;returns&amp;gt;true s'il y a encore des éléments après, false si c'est la fin.&amp;lt;/returns&amp;gt;
    public bool MoveNext()
    {
         bool resultat;
         m_Index++;
         if (m_Index &amp;amp;gt;= m_Parent.m_Values.Length)
             resultat = false;
         else
             resultat = true;
         Console.WriteLine(&amp;quot;### Appel de MoveNext(resultat={0})&amp;quot;, resultat);
         return resultat;
    }
    /// &amp;amp;lt;summary&amp;amp;gt;
    /// Réinitialise le pointeur d'élément pour retourner au premier.
    /// &amp;amp;lt;/summary&amp;amp;gt;
    public void Reset()
    {
         Console.WriteLine(&amp;quot;### Appel de Reset&amp;quot;);
         m_Index = -1;
    }
    #endregion
 }
</pre>
<h5>Trosième étape: écriture d&#8217;une classe de test</h5>
<p>Nous avons fait la plus grosse partie du travail, la classe de test montre comme utiliser notre itérateur.</p>
<pre class="brush: csharp; title: ; notranslate">
class TestIterateur
{
         static void Main(string[ args)
         {
           OldIterator iterator = new OldIterator();
           Console.WriteLine(&amp;quot;Les valeurs de l'iterateur:&amp;quot;);
           foreach (string value in iterator)
           {
                Console.WriteLine(&amp;quot;--&amp;amp;gt; &amp;quot; + value);
            }
            Console.ReadLine();
        }
 }
</pre>
<p>Cet exemple affiche ceci dans la console:</p>
<pre>
Les valeurs de l'iterateur:
### Appel de MoveNext(resultat=True)
### Appel de Current --&gt; a
### Appel de MoveNext(resultat=True)
### Appel de Current --&gt; b
### Appel de MoveNext(resultat=True)
### Appel de Current --&gt; c
### Appel de MoveNext(resultat=True)
### Appel de Current --&gt; d
### Appel de MoveNext(resultat=False)</pre>
<p>Le code source est disponible dans l&#8217;archive suivante: <a href="/donnees/sources/IteratorsTest.zip" hreflang="fr">IteratorsTest.zip</a> (4ko)</p>
<h4>Fonctionnement interne</h4>
<p>En analysant le résultat de l&#8217;exemple précédant, nous pouvons imaginer le fonctionnement de l&#8217;opérateur foreach.</p>
<pre class="brush: csharp; title: ; notranslate">
foreach (string element in iterator)
{
     Console.WriteLine(element);
}
</pre>
<p>Le compilateur génère l&#8217;équivalent du code suivant:</p>
<pre class="brush: csharp; title: ; notranslate">
while (iterator.MoveNext())
{
     string element = iterator.Current as string;
     Console.WriteLine(element);
}
</pre>
<p>Et voilà pourquoi il est plus facile d&#8217;utiliser l&#8217;opérateur foreach. La syntaxe est plus simple à coder et plus facile à comprendre. Ce chapitre vous a présenté le fonctionnement des itérateurs dans .NET 1.0/1.1. C&#8217;est un concept simple mais qu&#8217;il faut connaître car ils sont utilises partout dans le framework .NET. De plus, les itérateurs vous apportent de la souplesse dans le codage. Plus besoin de connaître la taille d&#8217;une liste, d&#8217;initialiser un curseur au premier élément, etc. Le chapitre suivant présentera les itérateurs dans .NET 2.0.</p>
<h3>Fonctionnement des itérateurs dans .NET 2.0</h3>
<h4>Utilisation d&#8217;un itérateur</h4>
<p>.NET 2.0 introduit un nouveau moyen pour implémenter facilement des itérateurs. Néanmoins, l&#8217;utilisation d&#8217;un itérateur est identique:</p>
<pre class="brush: csharp; title: ; notranslate">
foreach TypeElement element in liste_elements
{
     // Traiter 'element'.
}
</pre>
<p>La nouveauté par rapport à .NET 1.0/1.1 est l&#8217;introduction du mot clé <strong>yield</strong>. De plus, avec la possiblité d&#8217;utilier des generics depuis .NET 2.0, il est désormais possible de créer des itérateurs typés ce qui rend le code plus robuste (les erreurs sont détectables plus tôt par le compilateur).</p>
<h4>Implémentation</h4>
<p>Grâce au mot-clef yield, vous pourrez créer des itérateurs typés très facilement puisque le compilateur va générer un grande partie du code. yield permet de retourner une collection d&#8217;élément automatiquement. Le compilateur s&#8217;occupe de générer le code nécessaire.</p>
<h4>Exemple simple</h4>
<p>Voyons un petit exemple. Nous allons créer un itérateur qui retourne des entiers. Par contre, par rapport à l&#8217;exemple de .NET 1.0/1.1, désormais nous n&#8217;avons plus besoin de mettre en place l&#8217;index, la méthode MoveNext, Reset et la propriété Current. Tout ceci est fait par le compilateur.</p>
<pre class="brush: csharp; title: ; notranslate">
public class PowerIterator: IEnumerable&amp;amp;lt;int&amp;amp;gt;
{
     private int m_Number, m_Exponent;
     public PowerIterator(int number, int exponent)
     {
         m_Number   = number;
         m_Exponent = exponent;
     }
     // &amp;amp;lt;summary&amp;amp;gt;
     // Méthode statique qu'on peut appeler simple par PowerIterator.Power.
     // Elle retourne un itérateur d'entiers qui représente la suite q^n avec
     // q = number et n = exponent.
     // &amp;amp;lt;/summary&amp;amp;gt;
     // &amp;amp;lt;param name=&amp;quot;number&amp;quot;&amp;amp;gt;&amp;amp;lt;/param&amp;amp;gt;
     // &amp;amp;lt;param name=&amp;quot;exponent&amp;quot;&amp;amp;gt;&amp;amp;lt;/param&amp;amp;gt;
     // &amp;amp;lt;returns&amp;amp;gt;&amp;amp;lt;/returns&amp;amp;gt;
     public static IEnumerable&amp;amp;lt;int&amp;amp;gt; Power(int number, int exponent)
     {
         int counter = 0;
         int result = 1;
         while (counter &amp;amp;lt; exponent)
         {
             result = result * number;
             yield return result;
             counter++;
         }
     }

     #region IEnumerable&amp;amp;lt;int&amp;amp;gt; Members
     public IEnumerator&amp;amp;lt;int&amp;amp;gt; GetEnumerator()
     {
         return Power(m_Number, m_Exponent).GetEnumerator();
     }
     #endregion

     #region IEnumerable Members
     System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
     {
         return Power(m_Number, m_Exponent).GetEnumerator();
     }
     #endregion
}
</pre>
<p>Cette classe mérite quelques explications:</p>
<ul>
<li>Tout d&#8217;abord, on commence par indiquer qu&#8217;on implémente un itérateur de type int avec l&#8217;interface IEnumerable&lt;int&gt;,</li>
<li>Il y a deux méthodes dans cette interface: une méthode typée et une autre méthode non typée (pour rester compatible avec la version 1.0/1.1),</li>
<li>Chacun de ces méthodes retourne un énumérateur de type IEnumerator grâce à la méthode Power,</li>
<li>La méthode Power retourne une suite de nombres qui représente les puissances d&#8217;un entier passé en argument.</li>
</ul>
<p>Pour utiliser cet itérateur, voici une petite classe de démonstration. Elle propose deux moyens d&#8217;accès:</p>
<ul>
<li>soit en instanciant l&#8217;itérateur et en utilisant le mot-clef foreach sur cette instance (méthode utilisée avec .NET 1.0/1.1),</li>
<li>soit en appelant directement la méthode Power qui retourne l&#8217;itérateur sous la forme IEnumerable&lt;int&gt;.</li>
</ul>
<pre class="brush: csharp; title: ; notranslate">
class Program
{
     static void Main(string[ args)
     {
         PowerIterator iterator = new PowerIterator(2, 5);
         // L'utilisation d'un itérateur typé permet de détecter une erreur
         // si on utilise le mauvais type en tant qu'élément.
         Console.WriteLine(&amp;quot;Puissances de 2:&amp;quot;);
         foreach (int n in iterator)
         {
             Console.WriteLine(n);
         }

         Console.WriteLine();
         // Un moyen encore plus simple pour accéder à l'itérateur:
         Console.WriteLine(&amp;quot;Puissances de 3:&amp;quot;);
         foreach (int n in PowerIterator.Power(3, 5))
         {
             Console.WriteLine(n);
         }
         Console.ReadLine();
     }
}
</pre>
<p>Comme vous pouvez le constater, l&#8217;utilisation d&#8217;un itérateur est toujours aussi simple. Par contre, l&#8217;implémentation a été encore simplifiée puisqu&#8217;il suffit de générer une liste d&#8217;élément et de les retourner avec yield.</p>
<p>Cependant, avant d&#8217;utiliser ce mécanisme partout dans votre code, il convient de savoir ce que fait vraiment le compilateur. En effet, en ignorant son fonctionnement, on pourrait se retrouver avec une application lente ou qui ne fonctionne pas comme il faut. L&#8217;ensemble des codes sources est disponible dans l&#8217;archive: IteratorsDotnet2.zip</p>
<h4>Fonctionnement interne</h4>
<h5>Première approche</h5>
<p>Pour arriver à comprendre le fonctionnement de l&#8217;opérateur yield, j&#8217;ai utilisé l&#8217;outil Reflector .NET (de Lutz Roeder) qui permet de désassembler le code et de générer une représentation équivalente en C#. Voici une représentation du code généré par le compilateur pour notre itérateur (les noms générés ont été traduits à la main pour plus de compréhension):</p>
<pre class="brush: csharp; title: ; notranslate">
internal class PowerIterator : IEnumerable&amp;amp;lt;int&amp;amp;gt;, IEnumerable
{
      // Methods
      public PowerIterator(int number, int exponent);
      public IEnumerator&amp;amp;lt;int&amp;amp;gt; GetEnumerator();
      public static IEnumerable&amp;amp;lt;int&amp;amp;gt; Power(int number, int exponent);
      IEnumerator IEnumerable.GetEnumerator();

      // Fields
      private int m_Exponent;
      private int m_Number;

      // Nested Types
      private sealed class InternalPowerIterator : IEnumerable&amp;amp;lt;int&amp;amp;gt;, IEnumerable,          IEnumerator&amp;amp;lt;int&amp;amp;gt;, IEnumerator, IDisposable
      {
            // Methods
            public InternalPowerIterator(int state);
            private bool MoveNext();
            IEnumerator&amp;amp;lt;int&amp;amp;gt; IEnumerable&amp;amp;lt;int&amp;amp;gt;.GetEnumerator();
            IEnumerator IEnumerable.GetEnumerator();
            void IEnumerator.Reset();
            void IDisposable.Dispose();

            // Properties
            int IEnumerator&amp;amp;lt;int&amp;amp;gt;.Current { get; }
            object IEnumerator.Current { get; }

            // Fields
            private int m_state;
            private int m_current;
            public int m_exponent;
            public int m_number;
            public int m_counter;
            public int m_result;
            public int exponent;
            public int number;
      }
}
</pre>
<p>En analysant rapidement ce code, nous constatons que le compilateur C# a généré une classe (ici InternalPowerIterator). Cette classe implémente les différentes interfaces pour les itérateurs et la gestion mémoire du garbage collector (IDisposable). Les méthodes PowerIterator.GetEnumerator n&#8217;ont pas changé.</p>
<p>La méthode PowerIterator.Power est décrite par le code suivant:</p>
<pre class="brush: csharp; title: ; notranslate">
public static IEnumerable&amp;amp;lt;int&amp;amp;gt; Power(int number, int exponent)
{
      PowerIterator.InternalPowerIterator result = new PowerIterator.InternalPowerIterator(-2);
      result.m_number = number;
      result.m_exponent = exponent;
      return result;
}
</pre>
<p>Cette méthode instancie la classe InternalPowerIterator, initialise ses membres puis retourne le résultat. Nous pouvons donc en déduire que le compilateur génère automatiquement une classe interne qui sera utilisée pour notre itérateur. La méthode Power permet d&#8217;instancier cette classe généré.</p>
<h5>Etude de la classe générée</h5>
<p>Cette classe contient un ensemble de méthodes que nous allons analyser en détails.</p>
<p><strong>Constructeur</strong></p>
<p>Le constructeur de InternalPowerIterator prend en paramètre un entier qui indique un état (state).</p>
<p><strong>MoveNext</strong></p>
<pre class="brush: csharp; title: ; notranslate">
private bool MoveNext()
{
     switch (this.m_state)
     {
         case 0:
               this.m_state = -1;
               this.m_counter = 0;
               this.m_result = 1;
               while (this.m_counter &amp;amp;lt; this.exponent)
               {
                     this.m_result *= this.number;
                     this.m_current = this.m_result;
                     this.m_state = 1;
                     return true;
                  Label_0060:
                     this.m_state = -1;
                     this.m_counter++;
               }
               break;
         case 1:
               goto Label_0060;
      }
      return false;
}
</pre>
<p>Cette méthode nous en apprend plus sur l&#8217;attribut m_state. Il s&#8217;agit très probablement de l&#8217;état d&#8217;un automate. En effet, en regardant le code switch, nous remarquons qu&#8217;il s&#8217;agit du code d&#8217;un automate à état très simple. Celui-ci ne gère que trois états: -2, 0 et 1. L&#8217;état -2 est réservé et indique probablement que l&#8217;automate n&#8217;est pas dans un état correcte. L&#8217;état 0 est celui qui initialise les membres de la classe est début la boucle while. L&#8217;état 1 permet de continuer la boucle while à l&#8217;aide du goto.</p>
<p><strong>GetEnumerator</strong></p>
<pre class="brush: csharp; title: ; notranslate">
IEnumerator&amp;amp;lt;int&amp;amp;gt; IEnumerable&amp;amp;lt;int&amp;amp;gt;.GetEnumerator()
{
    PowerIterator.InternalPowerIterator result;
    // Comparaison de l'état actuel avec l'état -2 (non initialisé).
    if (Interlocked.CompareExchange(ref this.m_state, 0, -2) == -2)
    {        // Si m_state = -2, alors m_state = 0 et retourner la mÃªme instance.
        result = this;
    }
    else
    {
        // Sinon retourner une nouvelle instance initialisée.
        result = new PowerIterator.InternalPowerIterator(0);
    }
    result.number = this.m_number;
    result.exponent = this.m_exponent;
    return result;
}

IEnumerator IEnumerable.GetEnumerator() {
     // Retourne une énumérateur à partir de la méthode IEnumerable&amp;amp;lt;int&amp;amp;gt;.GetEnumerator().
     return this.System.Collections.Generic.IEnumerable&amp;amp;lt;System.Int32&amp;amp;gt;.GetEnumerator();
}
</pre>
<p>La première méthode est très importante pour cette classe. C&#8217;est elle qui permet d&#8217;initialiser la valeur de m_state (l&#8217;état de l&#8217;automate). Elle utilise la méthode Interlocked.CompareExchange qui permet une comparaison/échange thread-safe et retourne une instance de son propre type. Pour le résultat, l&#8217;état est initialisé à 0.</p>
<p><strong>Reset</strong></p>
<p>Le code génère une exception indiquant que la méthode n&#8217;est pas implémentée. Reset() n&#8217;est donc pas supporté dans .NET 2.0.</p>
<p><strong>Dispose</strong></p>
<p>Cette méthode ne contient rien pour le moment.</p>
<p><strong>La propriété Current</strong></p>
<pre class="brush: csharp; title: ; notranslate">
int IEnumerator&amp;amp;lt;int&amp;amp;gt;.Current
{
      get
      {
            return this.m_current;
      }
}

object IEnumerator.Current
{
      get
      {
            return this.m_current;
      }
}
</pre>
<p>Rien à dire: les deux méthodes retournent l&#8217;élément courant.</p>
<p><strong>Analyse des observations</strong></p>
<p>Nous remarquons que le code généré par le compilateur constitue un automate à état qui comporte quatre états:</p>
<ul>
<li>l&#8217;état -2 indique que l&#8217;automate est invalide,</li>
<li>l&#8217;état 0 indique qu&#8217;il faut initialiser l&#8217;automate,</li>
<li>l&#8217;état 1 indique qu&#8217;il est initialisé et que l&#8217;on peut continuer le traitement,</li>
<li>l&#8217;état -1 indique que l&#8217;automate est en cours d&#8217;initialisation.</li>
</ul>
<p>La méthode MoveNext contient le traitement qui permet de générer les éléments. La méthode GetEnumerator retourne un énumérateur dont l&#8217;automate se retrouve dans l&#8217;état initial. Etant donné que la méthode Reset n&#8217;est plus supportée, GetEnumerator retourne à chaque fois une nouvelle instance initialisé dans l&#8217;état 0 (indique le début de l&#8217;itération).</p>
<h3>Bilan général</h3>
<p>Nous avons vu qu&#8217;il devient très facile d&#8217;écrire des itérateurs grâce au mot-clef yield. Vous savez désormais que le compilateur génère une classe interne à notre implémentation qui permet de gérer un automate à états qui s&#8217;occupe de lister les éléments pendant les itérations. Il est important de noter que l&#8217;automate peut devenir complexe en fonction de votre traitement. Il ne faut pas non plus oublier que chaque boucle foreach va demander au runtime une nouvelle instance de la classe d&#8217;itération. Il faudra donc veiller à la consommation mémoire.</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.pascallacroix.net/blog/2006/10/25/introduction-aux-iterateurs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

