1.5. foreach tableaux et collections


Plan général:   ...........retour au plan général


1. Les collections

1.1 Les composants en général
1.2 Les contrôles sur un formulaire
1.3 Influence de la propriété parent sur l'affichage visuel d'un contrôle
1.4 Des graphiques dans les formulaires avec le GDI+
1.5 Le dessin doit être persistant
1.6 Deux exemples de graphiques sur plusieurs contrôles
        - méthode générale pour tout redessiner
        - des dessins sur événements spécifiques



1. foreach

L'instruction foreach répète un groupe d'instructions incorporées pour chaque élément d'un tableau ou d'une collection. L'instruction foreach sert à itérer la collection pour obtenir les informations souhaitées, mais ne doit pas être utilisée pour modifier le contenu de la collection afin d'éviter les effets collatéraux imprévisibles. L'instruction prend la forme suivante :

foreach (type identifier in expression) statement


1. Les collections

Les données étroitement liées peuvent être gérées plus efficacement quand elles sont regroupées pour former une collection. Au lieu d'écrire un code distinct pour gérer chaque objet, vous pouvez utiliser le même code pour traiter tous les éléments d'une collection.

Pour manager une collection, vous pouvez utiliser la classe Array ou les classes System.Collections pour ajouter, supprimer et modifier des éléments individuels d'une collection ou une série d'éléments. Vous pouvez même copier une collection complète dans une autre collection.



1.1 les collections en général

Une collection est un ensemble d'objets du même type qui sont regroupés ensemble.

Les objets d'un type quelconque peuvent être regroupés en une collection du type Object afin de tirer parti des constructions inhérentes au langage. Par exemple, l'instruction C#  foreach s'attend à ce que tous les objets de la collection soient du même type.

Toutes les collections qui implémentent directement ou indirectement l'interface ICollection partagent plusieurs fonctionnalités en plus des méthodes qui ajoutent, suppriment ou recherchent des éléments :

Un énumérateur. Un énumérateur est un objet qui effectue une itération sur la collection qui lui est associée. Il peut être considéré comme un pointeur mobile vers un élément quelconque de la collection. Un énumérateur ne peut être associé qu'à une seule collection, mais une collection peut avoir plusieurs énumérateurs. L'instruction C# foreach (for each dans Visual Basic) utilise l'énumérateur et masque la complexité de manipulation de celui-ci.
Membres de la synchronisation. La synchronisation garantit la sécurité des threads lors de l'accès à des éléments de la collection. Par défaut, les collections ne sont pas thread-safe. Seules quelques classes de l'espace de noms Collections fournissent une méthode Synchronize qui crée un wrapper thread-safe par-dessus la collection. Cependant, toutes les classes de l'espace de noms Collections fournissent une propriété SyncRoot que des classes dérivées peuvent utiliser pour créer leur propre wrapper thread-safe. Une propriété IsSynchronized est également fournie pour déterminer si la collection est thread-safe.
La méthode CopyTo. Toutes les collections peuvent être copiées dans un tableau à l'aide de la méthode CopyTo ; cependant, l'ordre des éléments dans le nouveau tableau est déterminé par la séquence dans laquelle l'énumérateur les retourne. Le tableau résultant est toujours unidimensionnel avec une limite inférieure de zéro.

Les classes Collections sont généralement réparties en trois catégories :

Collections génériques. Il s'agit des variations communes des collections de données, telles que les tables de hachage, les files d'attente, les piles, les dictionnaires et les listes.
Collections binaires. Il s'agit de collections dont les éléments sont des bits indicateurs. Leur comportement est un peu différent de celui des autres collections.
Collections spécialisées. Ces collections répondent à des objectifs hautement spécifiques ; il s'agit généralement de gérer un élément de type spécifique, comme StringDictionary.
Veillez à choisir votre classe de collection avec beaucoup de soin. Si chaque collection a sa propre fonctionnalité, elle a également ses propres limites. Plus une collection est spécialisée, plus elle est limitée.

Veillez à choisir votre classe Collections avec beaucoup de soin. Le choix d'une collection erronée peut limiter l'usage que vous pouvez en faire.

Réfléchissez aux questions suivantes :

Avez-vous besoin d'une liste séquentielle dans laquelle l'élément est généralement abandonné une fois sa valeur extraite ?
Si la réponse est positive, pensez à Queue ou à Stack.
Si la réponse est négative, songez aux autres collections.
Avez-vous besoin d'accéder aux éléments dans un certain ordre, par exemple premier entré premier sorti, dernier entré premier sorti ou un ordre aléatoire ?
Queue offre un accès de type premier entré premier sorti.
Stack offre un accès de type dernier entré premier sorti.
Les autres collections offrent un accès aléatoire.
Avez-vous besoin d'accéder à chaque élément par son index ?
ArrayList et StringCollection offrent l'accès à leurs éléments par l'index de base zéro de l'élément.
Hashtable, SortedList, ListDictionary et StringDictionary offrent l'accès à leurs éléments par la clé de l'élément.
NameObjectCollectionBase et NameValueCollection offrent l'accès à leurs éléments par l'index de base zéro ou la clé de l'élément.
Chaque élément contiendra-t-il une seule valeur, une combinaison d'une clé et d'une valeur ou une combinaison d'une clé et de plusieurs valeurs ?
Une seule valeur : utilisez l'une des collections reposant surIList.
Une clé et une valeur : utilisez l'une des collections reposant sur IDictionary.
Une clé et plusieurs valeurs : utilisez la classe NameValueCollection de l'espace de noms System.Collections.Specialized.
Avez-vous besoin de trier les éléments dans un ordre différent de celui dans lequel ils ont été entrés ?
Hashtable trie les éléments selon le code de hachage de la clé.
SortedList trie les éléments par clé, sur la base d'une implémentation IComparer.
ArrayList fournit une méthode Sort qui accepte l'implémentation IComparer en tant que paramètre.
Avez-vous besoin d'opérations de recherche et d'extraction d'informations rapides ?
ListDictionary est plus rapide que Hashtable pour les petites collections (10 éléments ou moins).
Avez besoin de collections qui acceptent uniquement des chaînes ?
StringCollection (fondée sur IList) et StringDictionary (fondée sur IDictionary) font partie de l'espace de noms System.Collections.Specialized.



1.2 les contrôles sur un formulaire

L'ajout (et la suppression) de contrôles dans un contrôle conteneur de vos formulaires (comme le contrôle Panel ou GroupBox, voire le formulaire lui-même) représente une tâche courante du développent d'applications. Ces contrôles gèrent une collection Controls, qui assure le suivi des contrôles qui y sont placés.

public Control.ControlCollection Controls {get;}

Représente une collection d'objets Control.

Les méthodes Add, Remove et RemoveAt permettent d'ajouter et de supprimer des contrôles individuels de la collection. Vous pouvez également utiliser les méthodes AddRange ou Clear pour ajouter ou supprimer tous les contrôles de la collection.

Vous pouvez déterminer si Control est un membre de la collection en passant le contrôle dans la méthode Contains. Pour obtenir la valeur d'index de l'emplacement de Control dans la collection, passez le contrôle dans la méthode IndexOf. La collection peut être copiée dans un tableau en appelant la méthode CopyTo.

panel1.Controls.Add(newPanelButton);

panel1.Controls.Remove(newPanelButton);
newPanelButton.Dispose();


1.3 les hashtable

Représente une collection de paires valeur-clé qui sont organisées en fonction du code de hachage de la clé.
Chaque élément est une paire valeur-clé stockée dans un objet DictionaryEntry. Une clé ne peut pas être une référence null (Nothing dans Visual Basic), contrairement à une valeur.

Les objets utilisés comme clés dans Hashtable doivent implémenter ou hériter des méthodes Object.GetHashCode et Object.Equals. Si l'égalité des clés est simplement une égalité des références, l'implémentation de ces méthodes héritée suffit. De plus, ces méthodes doivent donner les mêmes résultats lorsqu'elles sont appelées avec les mêmes paramètres si la clé existe dans Hashtable. Les objets de clé doivent être immuables tant qu'ils sont utilisés comme clés dans Hashtable.

Quand un élément est ajouté à Hashtable, il est placé dans un compartiment basé sur le code de hachage de la clé. Les recherches suivantes de la clé utiliseront le code de hachage de cette clé pour ne rechercher que dans un compartiment précis, ce qui réduira substantiellement le nombre de comparaisons de clés nécessaire pour trouver un élément.

Le facteur de charge de Hashtable détermine le ratio maximal d’éléments par compartiment. Des facteurs de charge plus petits écourtent les temps moyens de recherche, mais augmentent la consommation de mémoire. Le facteur de charge par défaut est de 1, ce qui représente généralement le meilleur compromis entre la vitesse et la taille. Un facteur de charge différent peut être spécifié si Hashtable est créé.

Lorsque des éléments sont ajoutés à Hashtable, le facteur de charge réel de Hashtable augmente. Lorsque le facteur de charge réel devient égal au facteur de charge, le nombre de compartiments dans Hashtable est automatiquement augmenté au plus petit nombre premier supérieur à deux fois le nombre actuel de compartiments de Hashtable.

Chaque objet de clé dans Hashtable doit apporter sa propre fonction de hachage, qui est accessible en appelant GetHash. Cependant, tout objet implémentant IHashCodeProvider peut être passé à un constructeur de Hashtable et cette fonction de hachage est utilisée pour tous les objets de la table.