jeudi 4 juin 2009

cour vb 2008 vb.net




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 for each en Visual Basic s'attend à
ce que tous les objets de la collection soient du même type.



Cependant, dans une collection de type Object, les différents
éléments sont soumis à un traitement supplémentaire, des opérations boxing et
unboxing ou des conversions par exemple, qui pénalise les performances de la
collection.



Les conversions boxing et unboxing se produisent généralement en cas de
stockage ou d'extraction d'un type valeur dans une collection de type Object.



Les collections génériques, telles que

List
, et les collections non
génériques fortement typées, telles que

StringCollection
, évitent cette
dégradation des performances si le type de l'élément est le type auquel la
collection est destinée (par exemple, le stockage ou l'extraction de chaînes à
partir de StringCollection).



En outre, les collections fortement typées exécutent automatiquement la
validation du type de chaque élément ajouté à la collection.



Toutes les collections qui implémentent directement ou indirectement
l'interface

ICollection
ou l'interface
générique

ICollection
partagent plusieurs
fonctionnalités en plus des méthodes permettant d'ajouter, de supprimer ou de
rechercher des éléments :


1.1.
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 for each en Visual Basic utilise
l'énumérateur et masque la complexité de manipulation de celui-ci.


1.2.
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

System.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 System.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 synchronisation
n'est pas disponible dans l'interface générique ICollection.


Méthode CopyTo
.


Toutes les
collections peuvent être copiées dans un tableau à l'aide de la méthode
CopyTo
; toutefois, l'ordre des éléments dans le nouveau tableau dépend de
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.



Notez que l'interface générique ICollection possède des membres
supplémentaires que l'interface non générique n'inclut pas.



Les fonctionnalités suivantes sont implémentées dans certaines classes
de l'espace de noms System.Collections :


1.3.
Capacité et décompte.


La capacité d'une
collection est le nombre d'éléments qu'elle peut contenir. Le décompte d'une
collection est le nombre d'éléments qu'elle contient réellement.


BitArray
est un cas spécial ; sa
capacité équivaut à sa longueur, qui est la même que son décompte. Certaines
collections masquent la capacité ou le décompte, ou les deux.


Toutes les
collections de l'espace de noms System.Collections étendent
automatiquement leur capacité lorsque la capacité actuelle est atteinte. La
mémoire est réallouée et les éléments sont copiés de l'ancienne collection vers
la nouvelle. Le code nécessaire pour utiliser la collection est ainsi réduit,
mais les performances de la collection peuvent quand même s'en ressentir. La
meilleure façon d'éviter la dégradation des performances due à des réallocations
multiples est de définir une capacité initiale égale à la taille estimée de la
collection.


Limite
inférieure.


La limite
inférieure d'une collection est l'index de son premier élément. Toutes les
collections indexées dans l'espace de noms System.Collections ont une
limite inférieure de zéro.

Array
possède par défaut une
limite inférieure de zéro, mais une limite inférieure différente peut être
définie lors de la création d'une instance de la classe Array à l'aide de


CreateInstance
.



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


1.4.
Collections fréquemment utilisées.


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. Les
collections fréquemment utilisées possèdent des versions génériques et des
versions non génériques.


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, tel que

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. Pour des
conseils sur le choix d'une collection.




2.
Sélection d'une classe de collection



Veillez à choisir votre classe

System.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 récupérée ?


Si oui, vous devez
envisager d'utiliser la classe

Queue
ou la classe générique


Queue
si vous avez besoin d'un
comportement de premier entré premier sorti (FIFO).


Vous devez
envisager d'utiliser la classe

Stack
ou la classe générique
Stack
si vous avez besoin d'un comportement de dernier entré premier sorti (LIFO).


Sinon, vous devez
envisager d'utiliser les autres collections.


Devez-vous accéder
aux éléments dans un ordre précis, tel que FIFO, LIFO ou dans un ordre
aléatoire ?


La classe Queue
et la classe générique Queue proposent un accès FIFO.


La classe Stack
et la classe générique Stack proposent un accès LIFO.


La classe générique


LinkedList
autorise un accès
séquentiel à partir du début ou de la fin.


Les autres
collections offrent un accès aléatoire.


Avez-vous besoin
d'accéder à chaque élément par son index ?


Les classes


ArrayList
et


StringCollection
et la classe
générique

List
offrent l'accès à leurs
éléments par l'index de base zéro de l'élément.



Les classes

Hashtable
,

SortedList
,

ListDictionary
et

StringDictionary
, et les classes génériques

Dictionary
et

SortedDictionary
, offrent l'accès à leurs
éléments par la clé de l'élément.



Les classes

NameObjectCollectionBase
et

NameValueCollection
, et les classes
génériques

KeyedCollection
et

SortedList
, offrent l'accès à leurs
éléments par l'index de base zéro ou par 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 valeur : utilisez l'une des collections
basée sur l'interface

IList
ou l'interface générique

IList
.



Une clé et une valeur : utilisez l'une des
collections basée sur l'interface

IDictionary
ou l'interface générique

IDictionary
.


Une valeur avec clé
incorporée : utilisez la classe générique KeyedCollection.


Une clé et
plusieurs valeurs : utilisez la classe NameValueCollection.


Avez-vous besoin de
trier les éléments dans un ordre différent de celui dans lequel ils ont été
entrés ?


La classe
Hashtable
trie ses éléments par leurs codes de hachage.


La classe
SortedList
et les classes génériques SortedDictionary et
SortedList
trient leurs éléments par la clé, selon les implémentations de
l'interface

IComparer
et de l'interface
générique

IComparer
.


ArrayList
fournit une méthode

Sort
qui prend une
implémentation IComparer comme paramètre. Son équivalent générique, la
classe générique List, fournit une méthode

Sort
qui prend une
implémentation de l'interface générique IComparer comme paramètre.


Avez-vous besoin
d'opérations de recherche et de récupération d'informations rapides ?


ListDictionary
est plus rapide que Hashtable pour les petites collections (10 éléments
ou moins). La classe générique SortedDictionary fournit une capacité de
recherche plus rapide que la classe générique Dictionary.


Avez besoin de
collections qui acceptent uniquement des chaînes ?


StringCollection
(sur la base de IList) et StringDictionary (sur la base de
IDictionary
) figurent dans l'espace de noms

System.Collections.Specialized
.


En outre, vous
pouvez utiliser l'une des classes de collections génériques dans l'espace de
noms

System.Collections.Generic

comme collection de chaînes fortement typée en spécifiant la classe


String
de leurs arguments de
type générique.




3.
Présentation des collections ArrayList
et hashTable


Ce premier
article vous montre comment implémenter cet objet. Le but va être de créer une
classe collection cEmployes d'objets cEmploye.


3.1.
Créons cEmploye


Cette classe est
simple:




Public Class cEmploye

Private m_sNom As String



Public Property Nom() As String

Get

Nom = m_sNom

End Get

Set

m_sNom = Value

End Set

End Property



Public Sub New(ByVal sNom As String)

Nom = sNom

End Sub



End Class



Remarquez que
nous avons redéfinit le constructeur. On impose ainsi qu'une classe cEmploye ne
peut être créée que si l'on donne un nom à notre employé :




Dim objE = New cEmploye("IDRISSI Ahmed")


Dans un premier
temps, on va ajouter une variable privée à notre classe cEmployes :




Public Class cEmpoyes

Private mCol As Microsoft.VisualBasic.Compatibility.VB6.Collection

Public Sub New()

mcol = New Microsoft.VisualBasic.Compatibility.VB6.Collection()

End Sub

...

End Class


Pour
implémenter l'ajout d'un employé :





Public Function Add(ByVal sNom As String, ByVal sKey As
String) As cEmploye

Dim objE As New cEmploye(sNom)

mcol.Add(objE, sKey)

Add = objE

End Function


Vous voyez que
par défaut, j'impose l'utilisation d'une clé .

Pour les autres méthodes et propriétés (Item, Count et Remove),


Reste maintenant
à permettre au consommateur de notre classe de pouvoir faire des itérations.


C'est maintenant
beaucoup plus simple, il suffit d'utiliser l'interface IEnumerator mise à
disposition par l'objet Collection :




Public Function GetEnumerator() As IEnumerator

GetEnumerator = mcol.GetEnumerator

End Function


On peut faire
maintenant de l'itération sur notre objet :




Dim c As New cEmpoyes()

c.Add("Richard Clark", "clé")

For Each objTemp In c

Debug.WriteLine(objtemp.Nom)

Next


On va maintenant
utiliser une autre classe de type collection : ArrayList.


3.2.
ArrayList


Comme son nom
l'indique, cette classe stocke des objets dans un tableau dynamique (sans clé).

Notre classe cEmploye est la même. En revanche, la classe cEmploye a quelque
peut changé.En voici le code complet :





Public Class cEmployes

Private mCol As ArrayList



Public Sub New()

mCol = New ArrayList()

End Sub



Public Function GetEnumerator() As IEnumerator

GetEnumerator = mCol.GetEnumerator

End Function



Public Function Add(ByVal sNom As String) As cEmploye

Dim objE As New cEmploye(sNom)

mCol.Add(objE)

Add = objE

End Function



Public ReadOnly Property Item(ByVal iIndex As Integer) As cEmploye

Get

Item = mCol.Item(iIndex)

End Get

End Property



Public ReadOnly Property Count() As Integer

Get

Count = mCol.Count

End Get

End Property



Public Sub Remove(ByVal sKey As String)

mCol.Remove(sKey)

End Sub

End Class


Le principe est
donc identique. En revanche, pour obtenir un élément dans la collection, il faut
connaitre son index.


Autre type de
collection est : HashTable.


3.3.
HashTable


Cette fois-ci,
cette collection associe à chaque élément de la collection une clé obligatoire.





Public Class cEmployes

Private mHashCol As Hashtable



Public Sub New()

mHashCol = New Hashtable()

End Sub



Public Function GetEnumerator() As IEnumerator

GetEnumerator = mHashCol.Values.GetEnumerator

End Function



Public Function Add(ByVal sNom As String, ByVal sKey As String) As
cEmploye

Dim objE As New cEmploye(sNom)

mHashCol.Add(sKey, objE)

Add = objE

End Function



Public ReadOnly Property Item(ByVal sKey As String) As cEmploye

Get

Item = mHashCol.Item(sKey)

End Get

End Property



Public ReadOnly Property Count() As Long

Get

Count = mHashCol.Count

End Get

End Property



Public Sub Remove(ByVal sKey As String)

mHashCol.Remove(sKey)

End Sub

End Class


Vous aurez
remarqué que l'itération se fait sur le tableau des valeurs :




GetEnumerator = mHashCol.Values.GetEnumerator



4.
Exemple



selon une propriété avec IComparable mais
également comment la trier suivant plusieurs propriétés avec des IComparer (sans
écrire le moindre algo de tri)



C'est en lisant
un thread sur un newsgroup que j'ai vu cette astuce (j'avoue ne pas avoir noté
le nom de la personne qui donnait cette astuce mais si elle se reconnait,
qu'elle n'hésite pas à me le dire,


Bref, la
question était la suivante :


4.1.
Trier des objets selon une de leur
propriété.


Avec le
Framework, no problemo, il suffit de lui implémenter l'interface IComparable et
la plupart des objets collection du Framework feront le travail pour vous.
Prenons l'exemple d'une classe Personne avec les propriétés suivantes :




















Classe Personne


Nom


string


Age


int


Taille


float



Maintenant,
remplissons un ArrayList de Personnes :




oAr.Add(new Personne("Said", 40,1.7f));

oAr.Add(new Personne("Ahmed", 30,1.5f));

oAr.Add(new Personne("Mounir", 20,1.6f));

oAr.Add(new Personne("Kamal", 10,1.8f));


Nous voulons que
par défaut, il soit trié suivant le Nom de la Personne. Implémentons donc
IComparable dans la classe Personne :






public class Personne : IComparable

{

public int CompareTo(object obj)

{

if (obj.GetType() != typeof(Personne))

throw new ArgumentException("Impossible de comparer les
choux et les carottes");

return this.Nom.CompareTo(((Personne) obj).Nom);

}

//

//

}


Pour trier
l'ArrayList, il suffit alors d'utiliser sa méthode Sort :




oAr.Sort();


Et voilà, notre
collection est triée suivant le Nom. Fastoche. Quoi ? Vous dites ? Ah, vous avez
une autre question ? Et alors ?


4.2.
Je voudrais maintenant les trier suivant
leur taille.


C'est là ou
l'astuce intervient (remarquez, il suffit de le savoir). La méthode Sort de l'ArrayList
a plusieurs signatures, 3 pour être précis. La signature qui nous intéresse ici
attends juste un argument, un IComparer. C'est lui qui va nous aider a trier les
personnes suivant leur taille.


Créons donc une
classe, implémentant IComparer (que l'on déclarera interne à la Personne car
elle ne s'applique qu'à elle) et comparant les tailles :




public class Personne : IComparable

{

public class TailleComparer : IComparer

{

public int Compare(object x, object y)

{

if (x.GetType() != typeof(Personne) y.GetType() != typeof(Personne))


throw new ArgumentException("Impossible de comparer les
choux et les carottes");

return ((Personne) x).Taille.CompareTo(((Personne) y).Taille);

}

}

//

//

}


C'est tout.
Maintenant pour trier notre ArrayList suivant la taille, une ligne suffit :




oAr.Sort(new Personne.TailleComparer());


Vous pouvez
ainsi implémenter une autre classe pour comparer les Personnes suivant leur age.

Aucun commentaire:

Enregistrer un commentaire