IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Déclaration avec un Type donné


Sujet :

C#

  1. #1
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Suisse

    Informations forums :
    Inscription : Mars 2007
    Messages : 8
    Par défaut Déclaration avec un Type donné
    Bonjour à tous!

    J'ai une question à laquelle je n'ai pas trouvé de réponse ni sur ce forum ni sur Google et j'espère que l'un d'entre vous pourra m'aider

    je voudrais savoir comment déclarer, par exemple, une liste ou effectuer un foreach avec un type donné. C'est un peu difficile à expliquer alors voila un petit exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    //ma fonction avec le type passé en param
    public void maFonction(Type monType){
     
        //ne fonctionne pas
        IList<monType> uiList = new List<monType>();
     
        //ça non plus
        foreach (monType serverElt in serverList)
            ...
    }
    j'espère que ma question est assez compréhensible...

    merci d'avance pour votre aide.

  2. #2
    Membre Expert
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    2 210
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2004
    Messages : 2 210
    Par défaut
    Quelle est l'erreur fournit par ton compilateur ?

    et qu'est-ce que 'serverList' ? (peut-être 'uiList' ?)

    Qui plus est 'monType' n'est pas un Type mais une valeur...

  3. #3
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Par défaut
    En clair tu souhaite manipuler une liste avec une liaison de type "TARDIVE"...

    Malheureusement tu ne peux pas procéder de la sorte.
    Tu pourrais mais cela reste relativement complexe avec de l'injection de code dynamique, et c'est pas propre.

    Le mieux que tu puisse faire dans ton cas c'est ainsi

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    public void MaFonction<T>()
    {
    List<T> uiList = new List<T>();
    ...
    foreach (T elem in uiList) {
    ...
    }
    }
    Cette fonction "générique" peut être intégrée dans une classe non générique sans problème, car seule la fonction l'est dans ce cas.
    Malheureusement, même là il est difficile de règler ton problème dans la mesure ou tu n'a pas une détermination du type dynamique mais bien à la compilation quand même.

    Tu ne peux pas utiliser les classes génériques sur des types déterminés à l'exécution. Il faut utiliser alors le type racine object, et manipuler toi meme le type (tu le connais il té fourni) malheureusement le transtypage par reflexion n'est pas évident.

    Quand tu écrit ton code, avec le tout en typé normal, les List<int> par exemple sont converties directement à la compilation, le type int est résolu à la compilation. En réalité il a besoin du type pour faire son inférence de type et vérifier que ce que tu écrit est "sensé" et sémantiquement correcte. Dans certains cas il en a même besoin pour pouvoir allouer de la mémoire ... Malheureusement là tu souhaite travailler avec des données qui ne sont pas connues à l'avance... mais uniquement à l'exécution, or il va de soit que le code est donc déjà compilé... j'ai eu le meme problème, a une époque, et j'ai procédé par un injection de code et des factory de code, mais c'est peut etre t'embarquer dans une galère romaine, surtout si cela n'est pas primordial et que tu peux faire autrement.

  4. #4
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Suisse

    Informations forums :
    Inscription : Mars 2007
    Messages : 8
    Par défaut
    oui exactement, je souhaite manipuler une liste en "runtime"..

    alors en fait j'ai trouvé une solution qui a l'air de fonctionner:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Type genericType = typeof(List<>);
    Type constructedType = genericType.MakeGenericType(typeof(monType));
    object listOfField = Activator.CreateInstance(constructedType);
    Apparemment, listOfField est désormais une liste contenant le type spécifié en runtime. me reste plus qu'a trouver une solution pour la parcourir avec un foreach.

    je vais faire quelques petits tests avant de changer le status du POST en résolu.

    et j'espère que ça pourra également aider quelqu'un

  5. #5
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Par défaut
    il y a toutefois un probleme avec ton code... et de taille

    typeof(montype) va retourner le Type de l'objet Type, pas le contenu de montype... je sais pas si comprend la nuance quoi qu'il en soit, tu va manipuler une liste d'objet de type ce qui n'a pas de sens car dans ce cas écrire List<Type> eu été plus rapide.
    Il faut fournir directement montype plutot que typeof(montype)...

    List<Type> n'a de sens que si dans ta liste tu stocke divers type de données, et pense également que typeof(var) sur 2 var de meme type, retourne la meme instance de Type... Chaque type est décrit par une instance UNIQUE de Type associée.

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Suisse

    Informations forums :
    Inscription : Mars 2007
    Messages : 8
    Par défaut
    Citation Envoyé par cinemania Voir le message
    typeof(montype) va retourner le Type de l'objet Type, pas le contenu de montype... je sais pas si comprend la nuance quoi qu'il en soit, tu va manipuler une liste d'objet de type ce qui n'a pas de sens car dans ce cas écrire List<Type> eu été plus rapide.
    Il faut fournir directement montype plutot que typeof(montype)...
    justement, IList<monType> uiList = new List<monType>(); ne fonctionne pas, le compilateur n'a pas l'air d'aimer

    En fait, le contenu de monType n'a pas d'importance, je n'ai besoin que du type pour pouvoir générer une liste. celle-ci sera remplie via une fonction qui va me retourner des objets de type monType.

    c'est difficile à expliquer, le projet sur lequel je travaille utilise énormément la Reflection .NET (je suis arrivé en plein milieu de projet et il est assez conséquent) et la Reflection est quelque chose d'assez nouveau pour moi!

    en tout cas, mon code a résolu une bonne partie de mon problème!

  7. #7
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Par défaut
    C'est ce qu je t'ai dit tout a l'heure ca ne marche pas c'est normal,

    cependant ton nouveau code n'est pas correct non plus, mais là le compilateur est dans l'incapacité de le détecter... c'est le problème de l'analyse sémantique de ce que l'on écrit lorsque l'on utilise la Reflexion... yen a plus !

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    Type genericType = typeof(List<>);
    Type constructedType = genericType.MakeGenericType(monType);
    object listOfField = Activator.CreateInstance(constructedType);
    permet ici de manipuler une liste d'objets du type fourni en paramètre. sinon comme je disais tu manipule une liste de types ce qui n'est pas du tout la meme chose.

  8. #8
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Suisse

    Informations forums :
    Inscription : Mars 2007
    Messages : 8
    Par défaut
    d'accord, je vois ce que tu veux dire, je ne comprenais pas ce que tu m'expliquais
    par contre, cela n'a pas l'air de poser de problème!

    j'ai fait le test de passer à ma fonction typeof(string), et le résultat n'est pas une liste de type mais bel et bien une liste de string que je peux utiliser de la même façon que si j'avais utilisé la déclaration IList<string> uiList = new List<string>();

    tu vois ce que je veux dire ou c'est moi qui suis complètement à coté de la plaque?

    merci pour ton aide

  9. #9
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Par défaut
    c'est bon

  10. #10
    Rédacteur
    Avatar de SaumonAgile
    Homme Profil pro
    Team leader
    Inscrit en
    Avril 2007
    Messages
    4 028
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Team leader
    Secteur : Conseil

    Informations forums :
    Inscription : Avril 2007
    Messages : 4 028
    Par défaut
    Citation Envoyé par cinemania Voir le message
    Quand tu écrit ton code, avec le tout en typé normal, les List<int> par exemple sont converties directement à la compilation, le type int est résolu à la compilation.
    Juste pour être sûr que tout est correct, quand tu parles de compilation, tu parles bien du JITting ?
    Parce que les types génériques restent génériques dans le code MSIL, ce n'est qu'au JITting que le type complet non générique est compilé.
    Besoin d'un MessageBox amélioré ? InformationBox pour .NET 1.1, 2.0, 3.0, 3.5, 4.0 sous license Apache 2.0.

    Bonnes pratiques pour les accès aux données
    Débogage efficace en .NET
    LINQ to Objects : l'envers du décor

    Mon profil LinkedIn - MCT - MCPD WinForms - MCTS Applications Distribuées - MCTS WCF - MCTS WCF 4.0 - MCTS SQL Server 2008, Database Development - Mon blog - Twitter

  11. #11
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Par défaut
    oui

    c'est ca... sinon l'injection de code poserait porbleme
    et on aurait pas non plus accès a la méthode qu'il a utilisé.

  12. #12
    Membre habitué
    Profil pro
    Inscrit en
    Mars 2007
    Messages
    8
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : Suisse

    Informations forums :
    Inscription : Mars 2007
    Messages : 8
    Par défaut
    Mon problème est résolu..

    j'ai donc séparé mon code en 2 parties, l'une crée mon objet uiList qui contiendra plus tard des objets de type monType et l'autre appel la fonction Add pour insérer un élément dans la liste.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    //déclaration de la liste
    Type genericList = typeof(List<>);
    Type listGenericType = genericList.MakeGenericType(monType);
    object uiList = Activator.CreateInstance(listGenericType);
     
    //utilisation (appel de fonction add)
    Type listType = uiList.GetType();
    object[] param = new object[] { ... };
    listType.GetMethod("Add").Invoke(uiList, param);
    Je vous avoue que n'étant pas un expert en c#, certaines terminologies voir même certains concepts me sont peu compréhensibles.
    Le projet sur lequel je travail est très spécifique et très complexe donc il m'est impossible de vous expliquer en détail pourquoi je DOIS utiliser une méthode de ce genre.

    j'espère seulement que le petit code que je vous ai déposé permettra d'aider quelqu'un pour un problème du même genre.

    encore merci à tous pour votre aide

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème avec le type de données date.
    Par oioire dans le forum Débuter
    Réponses: 3
    Dernier message: 01/11/2012, 14h58
  2. [SQL] Jointure avec des type des données différents
    Par Deciprog dans le forum SAS Base
    Réponses: 4
    Dernier message: 23/04/2010, 14h07
  3. haxe - array multidimensionnel avec 2 types de données
    Par Haxor668 dans le forum Flash/Flex
    Réponses: 2
    Dernier message: 28/04/2009, 19h51
  4. Réponses: 3
    Dernier message: 04/04/2007, 11h25
  5. [VB6] Problème mysql avec type données BLOB
    Par KrusK dans le forum VB 6 et antérieur
    Réponses: 1
    Dernier message: 20/06/2006, 11h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo