Fonction de recherche dans les generics sous C# 2.0
Fort content d’avoir decouvert les generics avec la nouvelle version du C# 2.0 (et .NET 2), ils permettent de créer des collections typées evitant toutes les problematies du boxing/unboxing ! En gros un generics est ni plus ni moins qu’un conteneur d’objet.
Petit exemple :
1 2 3 4 5 | List<string> monGenerics = new List<string>(); string test1 = "toto"; string test2 = "tata"; monGenerics.Add(test1); monGenerics.Add(test2); |
Cela nous permet d’avoir dans monGenerics 2 objets de types string qui sont ici test1 et test2.
Plein de methodes et/ou proprietes existent sur ces objets conteneur dont les principaux :
- Count : pour renvoyer un ‘int’ du nombre d’objet dans notre generics (ici : 2)
- Add & AddRange : pour ajouter un objet ou une collection de plusieurs objets
- Remove & RemoveAll & RemoveAt : pour supprimer un objet, plusieurs, ou par rapport a son index dans la generics
- etc…. (un petit coup de Reflector pour tout voir !!)
Mais dans ce post nous allons seulement nous interresser aux methodes de recherche dans notre Generics grâce aux methodes suivantes : Find, FindAll, FindIndex (il existe aussi FindLast et FindLastIndex mais nous ne le developperons pas dans ce post).
- Find : permet de rechercher un objet dans notre générics ! Il renvoi donc un objet de meme type que notre generics (dans notre exemple, cette fonction renverra un ‘string’)
- FindAll : permet de rechercher plusieurs objets, il renverra dans un generics de meme type (dans notre exemple, cette fonction renverra un ‘List<string>’)
- FindIndex : permet de recuperer l’index de l’objet rechercher. Il renvoi un ‘int’.
Ces 3 methodes prennent en argument un Predicate qui sera notre condition de recherche (un genre de WHERE en SQL). A noter que la methode FindIndex peut etre surchargé des arguments startIndex et count en ‘int’.
Pour faire une bonne fonction de recherche, personnellement j’utilise un délégué comme Predicate qui pointe faire une fonction boolean qui est a true si l’objet respecte bien notre condition de recherche.
Le mieux est de comprendre par un exemple :
- Nous allons créer une structure nommé Personne qui contiendra 3 proprietes : Nom, Prenom et Ville pouvant etre remplit via le constructeur de notre structure.
- Nous créons plusieurs personnes que nous ajouterons a notre Generics de type Personne :
1 2 3 4 5 6 | List<Personne> maListe = new List<Personne>(); maListe.Add(new Personne("WARIN","Sébastien","Lambersart")); maListe.Add(new Personne("WARIN","Julien","Lambersart")); maListe.Add(new Personne("RENARD","Gregory","Villeneuve d'Ascq")); maListe.Add(new Personne("DUPONT","Henry","Paris")); maListe.Add(new Personne("LAGAFFE","Gaston","Villeneuve d'Ascq")); |
1 | int indexDupond = maListe.FindIndex(new delegate(Personne personn) { return personn.nom == "DUPOND" }); |
Recherche avancé :
Nous allons ici créer une methode de recherche de type boolean sur le champs Nom :
1 2 3 4 5 6 | public bool FindByName(Personne personn, string name) { if(personn.Nom == name) return true; else return false; } |
Nous cherchons maintenant toutes les personnes ayant le nom « WARIN » :
1 2 | string condition = "WARIN"; List<Personne> warinPeople = maListe.FindAll(new delegate(Personne personn) { return FindByName(personn,condition) }); |
Ici notre generics warinPeople contiendra 2 objets Personne, pour Julien et Sébastien ! Biensûr dans cette exemple la fonction FindByName est très simple nous aurons pu ecrire cela directement dans notre délégué comme pour l’exemple avec l’index de Mr DUPONT. Mais cela pour montrer que notre délégué peut pointer vers une fonction de recherche de type boolean beaucoup plus complexe et prennant plusieurs arguments en entrée.
J’utilise actuellement cela pour mon projet SimImmuno II actuellement developpement, dont voici un exemple de code :
1 2 3 4 5 6 7 8 9 10 11 | public bool isCompatibleToCellLock(SCellule cellule1, SCellule cellule2, int dist_max) { bool tmp = false; if (TestCompatibilite(cellule1, cellule2)) { if (DistTo(cellule1.Location, cellule2.Location) < dist_max) { if (!TestIfLockCell(cellule2)) { tmp = true; } } } return tmp; } |
Le tout appelé par :
1 | List<SCellule> celluleVoisine = SimData.FindAll(new delegate(SCellule cell) { return isCompatibleToCellLock(cell,cellRef,dist_max) } ); |
Voila, quelques exemples des methodes de recherche dans un generics, j’espere avoir pu vous aider…
Plus d’info sur le site MSDN a l’adresse : http://msdn2.microsoft.com/library/6sh2ey19(en-US,VS.80).aspx
Micha
bonjour,
dans les méthodes Find, FindAll, FindIndex, etc… le délégué passé en argument ne doit pas être précédé du terme « new ».
Par exemple on écrira pas :
int indexDupond = maListe.FindIndex(new delegate(Personne personn) { return personn.nom == « DUPOND » });
mais on écrira :
int indexDupond = maListe.FindIndex(delegate(Personne personn) { return personn.nom == « DUPOND » });
sinon ça marche pas