Les collections sont un concept important en POO, et le support complet des collections en C# est l’un des meilleurs du langage.
Pourquoi utiliser des ensembles génériques ? Avant C# 2.0, les collections pouvaient être implémentées de deux manières principales : a. Utiliser ArrayList Mettre des objets directement dans l’ArrayList est intuitif, mais comme les éléments de la collection sont de type Object, il faut faire une conversion de types fastidieuse à chaque utilisation. b. Utiliser des classes de collection personnalisées Une pratique courante consiste à hériter d’une classe personnalisée de la classe abstraite CollectionBase et à implémenter une collection de types forte en encapsulant l’objet IList. Cette méthode nécessite d’écrire une classe personnalisée correspondante pour chaque type de collection, ce qui demande beaucoup de travail. L’émergence de collections génériques résout bien les problèmes ci-dessus, et une seule ligne de code peut être utilisée pour créer un ensemble d’un type spécifié. Qu’est-ce qui est générique ? Les génériques sont de nouveaux éléments dans C# 2.0 (appelés modèles en C++) qui sont principalement utilisés pour résoudre une série de problèmes similaires. Ce mécanisme permet de passer le nom de la classe comme argument au type générique et de générer l’objet correspondant. Il peut être préférable de considérer les génériques (y compris les classes, interfaces, méthodes, délégués, etc.) comme des modèles, où la partie variante est remplacée par le nom de classe transmis comme argument, ce qui donne une nouvelle définition de type. Le générique est un sujet relativement vaste, et je ne l’analyserai pas en détail ici, et ceux qui sont intéressés peuvent consulter les informations pertinentes. Comment créer une collection générique ? La classe générique List sous l’espace de noms System.Collections.Generic <T>est utilisée pour créer des collections, et la syntaxe est la suivante : [mw_shl_code=crèpère, vrai] <T> ListListOfT = nouvelle <T>Liste() ; [/mw_shl_code] Le « T » est le type à utiliser, qui peut être des types simples, tels que chaîne, int ou des types définis par l’utilisateur. Prenons un exemple précis.
La classe Person est définie comme suit : [mw_shl_code=csharp,true]classe Personne
{ _name de ficelles privées ; Nom Private Int _age ; Âge
Créer un objet Person Personne publique (nom de la chaîne, int âge) { this._name= Nom ; this._age = Âge ; }
Nom Nom de la chaîne publique { get { return _name ; } }
Âge public int Age { get { return _age ; } }
}
//创建Person对象 Personne p1 = nouvelle personne (« Zhang San », 30) ; Personne p2 = nouvelle personne (« Li Si », 20) ; Personne p3 = nouvelle personne (« Wang Wu », 50) ;
//创建类型为Person的对象集合 Personnes de la liste<Person> = nouvelle <Person>Liste() ;
//将Person对象放入集合 des personnes. Ajouter (p1) ; des personnes. Add(p2) ; des personnes. Ajouter (p3) ;
//输出第2个人的姓名 Console.Write(persons[1]. Nom) ; [/mw_shl_code] Comme vous pouvez le voir, les collections génériques simplifient grandement le code d’implémentation des collections, ce qui permet de créer facilement des collections de types spécifiés. De plus, les collections génériques offrent aussi des fonctions plus puissantes, regardons le tri et la recherche dans celles-ci. Tri des collections génériques Le tri repose sur la comparaison, et pour trier, il faut d’abord comparer. Par exemple, s’il y a deux nombres 1 et 2, pour les trier, il faut d’abord comparer ces deux nombres et les trier selon les résultats de la comparaison. Si vous voulez comparer des objets, la situation est un peu plus compliquée, par exemple, si vous comparez des objets Personne, vous pouvez comparer par nom ou âge, ce qui nécessite de déterminer les règles de comparaison. Un objet peut avoir plusieurs règles de comparaison, mais une seule règle par défaut, qui est placée dans la classe définissant l’objet. Les règles de comparaison par défaut sont définies dans la méthode CompareTo, qui appartient à l’interface générique IComparable<T>. Voir le code ci-dessous : [mw_shl_code=csharp,true]classe Personne :IComparable<Person>
{ Comparer par âge public int CompareTo(Personne p) { Rends ça. Âge - p.Âge ; } }[/mw_shl_code] Les paramètres de la méthode CompareTo sont un autre objet du même type à comparer, la valeur de retour est de type int, si la valeur de retour est supérieure à 0, cela signifie que le premier objet est supérieur au second objet, si la valeur de retour est inférieure à 0, cela signifie que le premier objet est inférieur au second, et si elle retourne 0, les deux objets sont égaux. Après avoir défini les règles de comparaison par défaut, vous pouvez trier la collection en utilisant la méthode Tri sans paramètres, comme suit : [mw_shl_code=csharp,true]// Trier la collection selon les règles par défaut des personnes. Trier() ;
//输出所有人姓名 foreach (Personne p en personnes)
{ Console.WriteLine(p.Name) ; L’ordre de sortie est « Li Si », « Zhang San » et « Wang Wu » }[/mw_shl_code] En pratique, il est souvent nécessaire de trier la collection selon diverses règles, ce qui nécessite la définition d’autres règles de comparaison, pouvant être définies dans la méthode Compare, qui appartient à <T>l’interface générique IComparer, veuillez consulter le code suivant : [mw_shl_code=csharp,true]classe NameComparer : IComparer<Person>
{ Instances de séquenceurs de stockage public statique NameComparer Default = nouveau NameComparer() ;
Comparer par nom public int Comparer (Personne p1, Personne p2) { return System.Collections.Comparer.Default.Compare(p1. Nom, p2. Nom) ; } }[/mw_shl_code] Les paramètres de la méthode Compare sont deux objets du même type à comparer, la valeur de retour est de type int, et les règles de traitement des valeurs de retour sont les mêmes que celles de la méthode CompareTo. Comparer.Default renvoie un objet Comparer intégré pour comparer deux objets du même type. Voici comment trier la collection avec ce comparateur nouvellement défini : [mw_shl_code=csharp,true]//Trier la collection par nom des personnes. Trier(NameComparer.Default) ;
//输出所有人姓名 foreach (Personne p en personnes)
{ Console.WriteLine(p.Name) ; L’ordre de sortie est « Li Si », « Wang Wu » et « Zhang San » }[/mw_shl_code] Vous pouvez aussi trier la collection en déléguant, d’abord, en définissant une méthode que le délégué appelle pour stocker les règles de comparaison, et vous pouvez utiliser une méthode statique. Voir le code ci-dessous : [mw_shl_code=csharp,true]classe Comparaison de Personne
{ Comparer par nom public static int Nom(Personne p1, Personne p2) { return System.Collections.Comparer.Default.Compare(p1. Nom, p2. Nom) ; } }[/mw_shl_code] Les paramètres de la méthode sont deux objets du même type à comparer, la valeur de retour est de type int, et la règle de traitement des valeurs de retour est la même que celle de la méthode CompareTo.Ensuite, trier la collection via le système générique de délégués intégré. Comparaison <T>: [mw_shl_code=crèpère, vrai] <Person> System.Nom de la comparaison = nouveau System.Comparison<Person>(PersonComparison.Name) ; des personnes. Trier (NomComparaison) ;
//输出所有人姓名 foreach (Personne p en personnes)
{ Console.WriteLine(p.Name) ; L’ordre de sortie est « Li Si », « Wang Wu » et « Zhang San » }[/mw_shl_code] On peut voir que ces deux dernières méthodes peuvent trier la collection selon les règles spécifiées, mais l’auteur préfère utiliser la méthode de délégation, et peut envisager de placer diverses règles de comparaison dans une classe puis de les appeler de manière flexible. Recherche de collections génériques La recherche consiste à trouver des éléments qui répondent à des conditions spécifiques de la collection, et plusieurs conditions de recherche peuvent être définies et appelées selon les besoins. Tout d’abord, définissez les critères de recherche comme suit : [mw_shl_code=csharp,true]classe PersonPredicate
{ Trouvez des personnes d’âge moyen (plus de 40 ans) public static bool MidAge (Personne p) { si (p.Âge >= 40) retour fidèle ; sinon return false ; } }[/mw_shl_code] Les critères de recherche ci-dessus sont placés dans une méthode statique avec un type de retour booléen, et les éléments de la collection remplissant certaines conditions rendent vrai, sinon faux.Puis recherchez dans la collection via le système de délégué générique intégré. <T>Prédicat : [mw_shl_code=crèpère, vrai] System.Predicate<Person> MidAgePredicate = nouveau <Person>System.Predicate(PersonPredicate.MidAge) ; Liste<Person> Personnes d’âge moyen = personnes. FindAll (MidAgePredicate) ;
//输出所有的中年人姓名 foreach (Personne p dans MidAgePersons)
{ Console.WriteLine(p.Name) ; Sortie « Wang Wu » }[/mw_shl_code] Extension des collections génériques Et si vous vouliez obtenir les noms de toutes les personnes du groupe, séparés par une virgule ? Étant donné que la fonctionnalité qu’une seule classe peut fournir est limitée, il est naturel de penser <T>à étendre la classe List, qui est aussi une classe et peut donc être étendue par héritage. Voir le code ci-dessous : [mw_shl_code=csharp,true]// Définir la classe de collection Persons Personnes de la classe : Liste<Person>
{ Obtenez les noms de tous les membres de la collection chaîne publique GetAllNames() { si (ceci. Compte == 0) retour « » ;
chaîne val = « » ; foreach (Personne p dans ce livre) { val += p.Name + « , » ; }
Retourne Val. Sous-string(0, val. Longueur - 1) ; }
}
//创建并填充Persons集合 Personnes PersonCol = nouvelles personnes() ; PersonCol.Add(p1) ; PersonCol.Add(p2) ; PersonCol.Add(p3) ;
//输出所有人姓名 Console.Write(PersonCol.GetAllNames()) ; Sortie « Zhang San, Li Si, Wang Wu »[/mw_shl_code] Résumé : Cet article se concentre sur l’utilisation des génériques en C# 2.0 pour implémenter les collections, ainsi que pour étendre la fonction de collection, et l’utilisation correcte des collections génériques peut réduire beaucoup de duplications de travail et améliorer considérablement l’efficacité du développement. En fait, les ensembles sont simplement une application typique des génériques, et si vous souhaitez en savoir plus sur les génériques, vous pouvez consulter d’autres documents pertinents. J’espère que cet article vous a été utile :-)
|