<?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>shebu mais C pas grave &#187; c# inside</title>
	<atom:link href="https://blog.developpez.com/shebu/pcategory/c-inside/feed" rel="self" type="application/rss+xml" />
	<link>https://blog.developpez.com/shebu</link>
	<description></description>
	<lastBuildDate>Wed, 29 Jul 2009 17:10:30 +0000</lastBuildDate>
	<language>fr-FR</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=4.1.42</generator>
	<item>
		<title>Itérateurs fortement typés</title>
		<link>https://blog.developpez.com/shebu/p7909/c-inside/iterateur</link>
		<comments>https://blog.developpez.com/shebu/p7909/c-inside/iterateur#comments</comments>
		<pubDate>Wed, 29 Jul 2009 10:09:28 +0000</pubDate>
		<dc:creator><![CDATA[shebu]]></dc:creator>
				<category><![CDATA[c# inside]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Les itérateurs sont des éléments essentiels du framework .net. Toutes les collections fournies par le framework implémentent cette facilité pour les développeurs. Simples à utiliser, permettant de produire un code élégant et léger, ils sont cependant plus rares dans les collections spécifiques mises en place par les développeurs. La faute, certainement à un passif lourd dans la première version du framework, où la mise en place était assez laborieuse. La version 2 du framework simplifie [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>Les itérateurs sont des éléments essentiels du framework .net. Toutes les collections fournies par le framework implémentent cette facilité pour les développeurs. Simples à utiliser, permettant de produire un code élégant et léger, ils sont cependant plus rares dans les collections spécifiques mises en place par les développeurs. La faute, certainement à un passif lourd dans la première version du framework, où la mise en place était assez laborieuse. La version 2 du framework simplifie les choses en introduisant le mot clé yield : ce raccourci permet d’éviter de coder toute la mécanique sous-jacente (c’est le compilateur c# qui s’en charge). </p>
<p>Cependant, pour le développeur soucieux de fournir des classes « propres », il reste un problème génant : à moins de passer par des types génériques, les itérateurs ne permettent pas de proposer une approche fortement typée.</p>
<p>Nous allons voir comment, en quelques lignes, corriger ce problème.</p>
<p><span id="more-1"></span><br />
Typiquement, l’utilisation d’un itérateur « maison » se fait de la façon suivante :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">foreach (object o in maCollectionPerso) &nbsp; <br />
{ <br />
&nbsp; maClassePerso o_tmp = (maClassePerso)o; <br />
&nbsp; o_tmp.MethodePerso(); <br />
}</div></div>
<p>Chaque élément que l’on récupère dans notre boucle foreach n’est pas nativement fortement typé, et l’on est obligé de faire un cast dans le corps de la boucle. </p>
<p>Pourtant, il existe une astuce, qui <strong>fonctionne aussi bien en c# 1.0 qu’en 2.0</strong>, qui permet de récupérer directement un objet correctement typé.</p>
<p>Imaginons que nous ayons 2 classes à coder : une classe « Personne », et une classe « Famille » ; la famille étant une collection de personnes.</p>
<p>La classe « Personne » est implémentée de la façon suivante :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class Personne &nbsp;<br />
{ <br />
&nbsp; public string Nom; <br />
&nbsp; public string Prenom; <br />
&nbsp;<br />
&nbsp; public Personne() <br />
&nbsp; { <br />
&nbsp; } <br />
&nbsp;<br />
&nbsp; public Personne(string nom, string prenom) <br />
&nbsp; { <br />
&nbsp; &nbsp; &nbsp; this.Nom = nom; <br />
&nbsp; &nbsp; &nbsp; this.Prenom = prenom; <br />
&nbsp; } <br />
&nbsp;<br />
&nbsp; public string DonneTonNom() <br />
&nbsp; { <br />
&nbsp; &nbsp; &nbsp; return this.Prenom + &quot; &quot; + this.Nom; <br />
&nbsp; } <br />
}</div></div>
<p>La classe « Famille » utilise un arraylist pour stocker les personnes de la famille :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class Famille <br />
{ <br />
&nbsp; System.Collections.ArrayList lesPersonnes; <br />
&nbsp;<br />
&nbsp; public Famille() <br />
&nbsp; { <br />
&nbsp; &nbsp; &nbsp; lesPersonnes = new System.Collections.ArrayList(); <br />
&nbsp; } <br />
&nbsp;<br />
&nbsp; public void Ajouter(Personne unePersonne) <br />
&nbsp; { <br />
&nbsp; &nbsp; &nbsp; lesPersonnes.Add(unePersonne); <br />
&nbsp; } <br />
}</div></div>
<p>L’objectif de codage de notre énumérateur pour la classe “Famille” est simple : il faut pouvoir écrire la boucle suivante :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">class Program <br />
{ <br />
&nbsp; static void Main(string[] args) <br />
&nbsp; { <br />
&nbsp; &nbsp; &nbsp; Personne p1 = new Personne(&quot;Mansoif&quot;, &quot;Gérard&quot;); <br />
&nbsp; &nbsp; &nbsp; Personne p2 = new Personne(&quot;Scroutedansmonsacado&quot;, &quot;Jessica&quot;); <br />
&nbsp; &nbsp; &nbsp; Personne p3 = new Personne(&quot;Mouraiparti&quot;, &quot;Mona&quot;); <br />
&nbsp;<br />
&nbsp; &nbsp; &nbsp; Famille laFamille = new Famille(); <br />
&nbsp; &nbsp; &nbsp; laFamille.Ajouter(p1); <br />
&nbsp; &nbsp; &nbsp; laFamille.Ajouter(p2); <br />
&nbsp; &nbsp; &nbsp; laFamille.Ajouter(p3); <br />
&nbsp; &nbsp; &nbsp; &nbsp;<br />
&nbsp; &nbsp; &nbsp; foreach (Personne unePersonne in laFamille) <br />
&nbsp; &nbsp; &nbsp; { <br />
&nbsp; &nbsp; System.Console.WriteLine(unePersonne.DonneTonNom()); <br />
&nbsp; &nbsp; &nbsp; } &nbsp; &nbsp; &nbsp; &nbsp; Console.Read(); <br />
&nbsp; } <br />
}</div></div>
<p><strong>Il n’y a pas de cast dans notre boucle foreach.</strong></p>
<p>Normalement, pour coder un iterateur, il faut implémenter l’interface system.collections.IEnumerable. Mais cette interface nous oblige à renvoyer des éléments de type object.<br />
La solution, pour arriver à notre exemple d’utilisation, est très simple : il suffit de ne pas implémenter IEnumerable !</p>
<p>En effet, pour que notre boucle foreach fonctionne, il faut (et il suffit) que la classe «Famille » implémente les méthodes <strong>GetEnumerator, MoveNext, Reset</strong>, et qu’elle fournisse un champ <strong>Current</strong>. Et en interne, il suffit de stocker l’indice de l’élément courant de notre itération.</p>
<p>L’écriture de ces méthodes est toute simple, et se fait, contrairement à l’implémentation classique en framework 1, sans l’utilisation de « nested class ». </p>
<p>On a donc, au final, la classe famille suivante :</p>
<div class="codecolorer-container text default" style="overflow:auto;white-space:nowrap;border:1px solid #9F9F9F;width:435px;height:300px;"><div class="text codecolorer" style="padding:5px;font:normal 12px/1.4em Monaco, Lucida Console, monospace;white-space:nowrap">public class Famille <br />
{ <br />
&nbsp; System.Collections.ArrayList lesPersonnes; <br />
&nbsp; public Famille() <br />
&nbsp; { <br />
&nbsp; &nbsp; &nbsp; lesPersonnes = new System.Collections.ArrayList(); <br />
&nbsp; } <br />
&nbsp;<br />
&nbsp; public void Ajouter(Personne unePersonne) <br />
&nbsp; { <br />
&nbsp; &nbsp; &nbsp; lesPersonnes.Add(unePersonne); <br />
&nbsp; } <br />
&nbsp;<br />
&nbsp; #region implementation de notre itérateur <br />
&nbsp;<br />
&nbsp; int index = -1; // Permet de stocker l’index de l’élément courant <br />
&nbsp;<br />
&nbsp; public Famille GetEnumerator() <br />
&nbsp; { <br />
&nbsp; &nbsp; &nbsp; return this; <br />
&nbsp; } <br />
&nbsp;<br />
&nbsp; public Personne Current <br />
&nbsp; { <br />
&nbsp; &nbsp; &nbsp; get <br />
&nbsp; &nbsp; &nbsp; { <br />
&nbsp; &nbsp; return (Personne)lesPersonnes[index]; <br />
&nbsp; &nbsp; &nbsp; } <br />
&nbsp; } <br />
&nbsp;<br />
&nbsp; public bool MoveNext() <br />
&nbsp; { <br />
&nbsp; &nbsp; &nbsp; index++; <br />
&nbsp; &nbsp; &nbsp; if (index &lt; lesPersonnes.Count) return true; <br />
&nbsp; &nbsp; &nbsp; else return false; <br />
&nbsp; } <br />
&nbsp;<br />
&nbsp; public void Reset() <br />
&nbsp; { <br />
&nbsp; &nbsp; &nbsp; index = -1; <br />
&nbsp; } <br />
&nbsp; #endregion <br />
}</div></div>
<p>La seule subtilité du code ci-dessus est dans la méthode GetEnumerator : on renvoie directement l’instance de Famille utilisée : c’est cette classe qui contient directement l’implémentation de l’iterateur.</p>
<p>L’intérêt de ne pas implémenter IEnumerable se voit dans le type de retour de notre propriété Current : on renvoie directement un objet de type Personne, le cast se faisant directement dans l’assesseur get.</p>
<p>Il faut quand même noter que, si on n’implémente pas IEnumerable, on ne peut pas utiliser le mot clé yield : ce mot clé est en effet un indicateur qui, associé à IEnumerable, permet au compilateur de créer lui-même l’implémentation façon framework 1 de l’itérateur. Mais le code à écrire étant trivial, cela ne pose pas trop de problème.</p>
]]></content:encoded>
			<wfw:commentRss></wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
