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 :

Problème de cast générique (T)


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre extrêmement actif
    Avatar de stailer
    Homme Profil pro
    Architecte technique
    Inscrit en
    Mars 2003
    Messages
    1 144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 1 144
    Billets dans le blog
    3
    Par défaut Problème de cast générique (T)
    Bonjour,

    J'ai un problème avec une classe que je suis en train de développer, qui comporter une interface avec un type générique.

    Tout d'abord voici le code de l'interface :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public interface ISimpleDaoResultset<T>
    {
            void EndFillQueryEvent(List<T> results);
     }
    Plus tard je crée une classe qui va l'utiliser :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
     public class ACTUALITES_EXTENDED_RESULTSET : ISimpleDaoResultset<ACTUALITES_EXTENDED>
    {
            public void EndFillQueryEvent(List<ACTUALITES_EXTENDED> results)
            {
     
            }
        }
    J'ai en parallèle une classe générique qui va me permettre de l'utiliser en récupérant les types etc.
    Mais je ne peux pas savoir le type exact à l'intérieur, donc j'ai un truc comme ça :

    List<dynamic> results = new List<dynamic>();

    InstanceDe_ACTUALITES_EXTENDED_RESULTSET.EndFillQueryEvent(results);
    Et là c'est le plantage !

    Ca me dit que je donne des arguments incorrects car je passe une List<dynamic> et non une List<ACTUALITES_EXTENDED>

    J'ai bien sûr essayé tout de suite ça :

    Type mT = ... //ici récupération du type ACTUALITES_EXTENDED
    List<typeof(mT )>
    Mais ça ne compile pas...

    D'ou ma question : ce que je veux faire est-il possible ? et si oui, l'un d'entre vous aurait-il la solution ?

    En vous remerciant,

  2. #2
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Bonjour.

    En supposant que EndFilmQueryEvent doit lire la liste, alors tu dois soit recréer une liste (via List<>.ConvertAll), soit modifier la signature de ta fonction pour qu'elle accepte un IEnumerable<> (pour profiter de la covariance) voire un IReadOnlyList<> à partir du dotnet 4.5. Grosso modo la covariance est permise sur les structures en lecture seule, pas en écriture. Car si toute énumération de chaînes est une énumération d'objets, en revanche une liste de chaînes ne peut pas accepter d'objets. Au passage il n'y a en général que peu de raisons de passer des IList et on préfère les énumérables, plus flexibles et autorisant la covariance.

    Si toutefois EndFillQueryEvent doit modifier la liste, alors il faut rendre cette méthode générique.


    PS : Attention avec le terme "plantage" pour parler des erreurs de compilation, ça peut nous induire en erreur.

  3. #3
    Membre extrêmement actif
    Avatar de stailer
    Homme Profil pro
    Architecte technique
    Inscrit en
    Mars 2003
    Messages
    1 144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 1 144
    Billets dans le blog
    3
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     Attention avec le terme "plantage" pour parler des erreurs de compilation
    Salut DonQuiche, merci pour ta réponse.

    Alors j'ai bien fait attention aux termes : dans le 1er cas, il s'agit bien d'un plantage à l'exécution (pb de cast). Alors que dans le 2ème, quand j'essaye de faire le List<typeof(MonObjet)> ça ne compile pas.

    Comme tu l'indiques en effet avec un IEnumerable on peut déjà faire plus de chose, notamment convertir un type List<dynamic>.

    Je suis donc parti la-dessus. J'ai également récupéré le type "final" qui doit être casté...
    Par contre maintenant comment l'utiliser ?

    Voici mon code simplifié :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    Type mTypeResultset = 
    Type.GetType( "ACTUALITES_EXTENDED_RESULTSET" );
     
     Type typeResult = mTypeResultset.GetMethod("EndFillQueryEvent").GetParameters().FirstOrDefault().ParameterType;
     
      IEnumerable<dynamic> results = new IEnumerable<dynamic>();
    Du coup comment remplacer

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
     IEnumerable<dynamic> results = new IEnumerable<dynamic>();
    par un truc comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     IEnumerable<typeResult > results = new IEnumerable<typeResult >();
    je suis finalement un peu dans le même problème....

  4. #4
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    J'ai un peu de mal à saisir ce que tu veux faire et j'ai l'impression, peut-être fausse, que tu t'es embarqué dans un machin bancal qui te conduit dans une impasse.

    Concernant ta question, pour construire des génériques à la volée il faut faire :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    Type listOfInt = typeof(List<>).MakeGenericType(typeof(int));

    Sauf que ça ne t'avance pas à grand chose et que c'est bien compliqué (et on peut exploiter dynamic pour faire automatiquement toute cette plomberie). Encore une fois je pense que le problème est en amont et que tu dois faire machine arrière. Quelques questions pour m'aider à comprendre :
    * Tu dis avoir utilisé des énumérables mais si ta méthode accepte désormais un IEnumerable<ACTUALITES_EXTENDED_RESULTSET> tu peux lui fournir ton IEnumerable<dynamic> donc où est le problème restant ?
    * Reçois-tu des "dynamic" ou est-ce toi qui les a introduits pour résoudre ton problème ? Sinon quel était le type le plus précis dont tu disposais ?
    * EndFillQueryEvent modifie t-elle la liste reçue en argument où la lit-elle ?


    Enfin je reviens un peu aux bases : pour passer un List<T1> à une méthode acceptant un List<T2>, soit on n'a pas vraiment besoin d'une liste et on met simplement des énumérables aux deux endroits, soit on a vraiment besoin d'une liste et alors il faut soit convertir/reconvertir soit rendre la méthode générique. Dans tous les cas tu ne feras pas passer un canard (List<T1>) pour un chevreuil (List<T2>) quelles que soient les bidouilles que tu utiliseras (réflexion ou dynamiques).

  5. #5
    Membre extrêmement actif
    Avatar de stailer
    Homme Profil pro
    Architecte technique
    Inscrit en
    Mars 2003
    Messages
    1 144
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Hautes Pyrénées (Midi Pyrénées)

    Informations professionnelles :
    Activité : Architecte technique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2003
    Messages : 1 144
    Billets dans le blog
    3
    Par défaut
    Ouais,
    J'essaye de comprendre là et en effet je me suis avancé un peu vite :

    En fait pour obtenir mon IEnumerable j'ai fait ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    List<dynamic> results = new List<dynamic>();
    resultset.EndFillQueryEvent(results.AsEnumerable());
    Ca compile mais ça plante avec la même erreur à l'execution.

    En fait le but c'est d'utiliser le résultat EndFillQueryEvent.
    Dans ma classe qui implémente ISimpleDaoResultset j'ai donc :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     public void EndFillQueryEvent(IEnumerable<ACTUALITES_EXTENDED> results)
      {
     
     }
    Et j'aimerais exploités ces résultats... Avec ce que je veux faire ils seraient donc castés automatiquement.

    Si je peux, j'aimerais de faire ça par exemple:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     public void EndFillQueryEvent(IEnumerable<dynamic> results)
      {
            var d = ((IEnumerable<ACTUALITES_EXTENDED>)results).ToList();
     }

  6. #6
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Citation Envoyé par stailer Voir le message
    Ca compile mais ça plante avec la même erreur à l'execution.
    En fait tel quel ça ne compile même pas, du moins pas avec un EndFillQueryEvent acceptant une énumération de ACTUALITES_EXTENDED.


    Ce que je peux te proposer c'est de caster tes dynamiques en ACTUALITES_EXTENDED :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    EndFillQueryEvent(results.Cast<ACTUALITES_EXTENDED>());
     
    public void EndFillQueryEvent(IEnumerable<ACTUALITES_EXTENDED> results)
    { 
        var d = results.ToList();
    }
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    EndFillQueryEvent(results);
     
    public void EndFillQueryEvent(IEnumerable<dynamic> results) 
    { 
        var d = results.Cast<ACTUALITES_EXTENDED>().ToList();
    }
    Je préfère la première solution, qui me semble plus propre puisque EndFillQueryEvent ne peut fonctionner qu'avec des ACTUALITES_EXTENDED, donc autant le faire apparaître dans la signature. Note que si ça lève une exception c'est qu'un de tes éléments n'est pas du type ACTUALITES_EXTENDED et ceci ne peut pas être contourné, à moins de le garder sous forme de "dynamic" et de ne jamais tenter de le caster en ACTUALITES_EXTENDED.



    Enfin attention avec dynamic, son usage est rarement justifié. Si tu l'as utilisé pour contourner une autre difficulté je t'invite là aussi à revenir en amont pour revenir sur cette décision.

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

Discussions similaires

  1. Problème de casting avec des génériques
    Par bountykiler dans le forum C++/CLI
    Réponses: 2
    Dernier message: 05/07/2012, 13h00
  2. [C#] Problème de Cast sur un type générique
    Par Bobbledople dans le forum C#
    Réponses: 2
    Dernier message: 10/06/2009, 11h04
  3. Problème de Cast générique
    Par pcayrol dans le forum C#
    Réponses: 14
    Dernier message: 24/01/2008, 15h02
  4. Problème de cast/serialization/externalization ?
    Par Linlin dans le forum CORBA
    Réponses: 1
    Dernier message: 06/12/2004, 16h46
  5. [C#] Problème de casting de @IDENTITY
    Par bilb0t dans le forum Accès aux données
    Réponses: 7
    Dernier message: 03/09/2004, 09h42

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