Bonjour,
Ya beaucoup de parole sur les génériques en C#.
Je sais pas ce que vous en pensez mais moi j'aimerai savoir comment ca marche.
Je remercie d'avance tout le monde, une explication sur ce que c'est et le fonctionnement de base sur ça. ^^
Bonjour,
Ya beaucoup de parole sur les génériques en C#.
Je sais pas ce que vous en pensez mais moi j'aimerai savoir comment ca marche.
Je remercie d'avance tout le monde, une explication sur ce que c'est et le fonctionnement de base sur ça. ^^
Alors avant les génériques, ou les templates sous C++ si t'en a déjà un peu fait (ce qui m'étonnerais vu la question)
Quand tu voulais définir une classe Matrice pour faire des maths... en supposant que cette classe n'existe pas déjà dans le framework...
tu avait différents choix...
et tu manipulais directement des int, mais dans ce cas tu devais fournir une implantation pour les double...
Code : Sélectionner tout - Visualiser dans une fenêtre à part public class Matrice { ... }
alors tu me diras... dans ce cas j'utilise object comme ca... je peux utiliser ma matrice sur tous les objets... effectivement c'est une solution...
Mais C# est un langage fortement typé. Le fait d'utiliser le type ancêtre object va empêcher le compilateur de faire ce qu'on appel de l'inférence de type et de t'éviter nombre d'erreurs.
Si ta matrice peut contenir à l'instant T à la fois des objets d'un type et d'un autre sans aucun lien d'héritage entre eux... alors une matrice d'object est ce qu'il te faut... mais en meme temps explique moi l'intéret d'une matrice mathématique si je n'ai pas des valeurs numériques à l'intérieur ?
C'est là que ce pose le problème, object peut tout etre et tu ne peux donc pas faire de calcul dessus, et il t'est donc impossible d'envisager les multiplications de matrices, ou tu va devoir te taper de la reflexion et des if à n'en plus finir pour gérer toi meme les types dynamiques manipulés...
Les génériques sont là pour ça.
Va définir une matrice générique réutilisable à souhait en définissant le type à la compilation... ainsi
Code : Sélectionner tout - Visualiser dans une fenêtre à part public class Matrice<T> { }
va t'instancier une matrice d'int...
Code : Sélectionner tout - Visualiser dans une fenêtre à part Matrice<int> iMatrice = new Matrice<int>();
C'est comme si t'avais toi meme codé la matrice avec des int, et une autre avec les double ...
car tu pourra avoirces matrices contiendrons des objets de meme type, ainsi tu pourra lors faire des calcul numériques en contraignant le type générique T à respecter certaines contraintes, comme le fait de ne pas être une class, mais une struct par exemple, ou d'implanter un des interfaces qui permettent le calcul et qui sont intuitivement implanté par les types natifs...
Code : Sélectionner tout - Visualiser dans une fenêtre à part Matrice<double> = new Matrice<double>()
Et oui, Matrice développées avec des objets qui ne doit manipuler que des Struct, c'est possible mais soit tu fait les controles à la mano à l'exécution, soit tu compte sur le développeur pour bien utiliser ta classe (vaut mieux oublier cette idée)
Avec les génériques et en contraignant le type générique T comme suite
tu vient de définir une classe matrice générique qui n'autorise la manipulation que de type par valeur, oh mais ca ressemble étrangement à ce qu'on voulait non ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part public class Matrice<T> where T: struct { ... }
ensuite tu va la manipuler directement comme étant une implantation de ta matrice pour le type voulu et non pas faire toi meme des Cast à tout bout de champs...
Voilà j'espère avoir été assez clair.
Ok, mais si tu veux utiliser cette matrice de int avec la syntaxe des générique, comment ca se passe, par exemple si tu veux modifier une seule ligne de la matrice sans devoir comme dans une arraylist :
- tout dépiler pour récupérer une ligne et son numéro de ligne,
- modifier la ligne,
- copier l'ancienne l'ancienne Arraylist dans une nouvelle arraylist
- vider l'ancienne arraylist et la reremplir avec la condition que s'il atteint le numéro de ligne -> copier la ligne modifiée
?
En faite c'est parce que je veux pouvoir stocker, ajouter, supprimer, mettre à jour des objets dans un conteneur sans devoir chercher des algorithmes super compliqués via les Arraylists...
mais ca marche comme les arraylist sauf que tu manipule des objet typé directement...
Et puis depuis dotnet 3, et tout particulièrement les méthodes d'extensions, et Linq, tout est devenu d'une facilité déconcertante...
en fait je vois pas ton problème d'algorithme là...
j'ai choisi une matrice comme j'aurais choisi autre chose... c'était un exemple.
au lieu d'utiliser ArrayList utilise List<T> dans System.Collections.Generic.
Exemple si tu ne doit manipuler que des Int
tu déclare une List<int> au lieu d'une arryalist pour stocker tes données.
pour les manipuler après tout dépend de ce que tu veux faire, mais les génériques ne sont pas là pour t'empêcher de faire des algorithmes hein...
c'est pas leur finalité.
l'intéret des génériques est de rendre l'écriture plus clair, de simplifier pas mal de développements, et surtout de permettre de détecter les inconsistance de type à la compilation et non comme un con à l'exécution et courrir après des bugs fantomes parce que t'a la sale habitude de foutre des try / catch partout avant même d'etre sure que ton code a pas d'autres effets que ceux auxquels tu t'attend et donc aux exceptions auxquelles tu t'attend.
si tu crois que les generics sont là pour t'empecher de reflechir et programmer... tu te trompe, ils vont te simplifier la vie, mais pas tout supprimer.
en revanche si tu veux sélectionner juste un fragment d'une collection sur un critère particulier tu as plusieurs solutions :
et filtre va contenir une énumération des éléments que tu as retenu...
Code : Sélectionner tout - Visualiser dans une fenêtre à part var filtre = from n in list where <critères> select n;
car ils remplisse les conditions where...
d'ailleurs Linq, et les méthodes d'extensions sont fortement typés, aussi se sont toutes des méthodes génériques...
mais tu peux maintenant éviter d'écrire le <int> car le moteur d'inférence de type le retrouvera tout seul.
Code : Sélectionner tout - Visualiser dans une fenêtre à part list.FirstOrDefault<int>()
Ca a l'air bien comme simplification ^^. Il me fallait partir de quelque chose pour aborder un nouveau principe.
Je me suis bien documenter sur le sujet et ça me donne plein d'idée dans la tête. ^^
J'ai vu que list<T> te permet de getter (récupérer, pour ceux qui sont pas anglophone) une ligne via ce qu'on appelle des indexeurs via :
J'ai vu que list<T> a également une méthode set pour updater (mettre à jour, pour ceux qui sont pas anglophone) une ligne via la même syntaxe.
Code : Sélectionner tout - Visualiser dans une fenêtre à part (Type) nomDeVariable = list<Type>.Item[numLigne]
Mais s'auré été bien qu'il donne aussi ces supers pouvoirs au arraylist, dommage.
Je vais faire des tests et je reviens. Merci.
moi je ferai un convert.toQuelqueChose, à toi de voir ^^
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager