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 :

genérique <T> et foreach


Sujet :

C#

  1. #1
    Membre expérimenté
    Homme Profil pro
    Administrateur Systèmes, Clouds et Réseaux /CAO/DAO/Ingénierie Electrotechnique
    Inscrit en
    Décembre 2014
    Messages
    457
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Administrateur Systèmes, Clouds et Réseaux /CAO/DAO/Ingénierie Electrotechnique

    Informations forums :
    Inscription : Décembre 2014
    Messages : 457
    Par défaut genérique <T> et foreach
    Bonjour, j'espère ne pas me planter en décrivant mon problème.

    J'ai créé une classe qui contient un block GetEnumerator. C'est une classe qui ne contient aucune méthode, que des paramètres si je ne me plante pas sur le vocabulaire (get set)

    Elle fonctionne très bien à la base.

    Je m'en sers pour faire une requête paramétrée et quand je lance ma méthode avec cette classe, tout fonctionne bien public int insertP(Maclasse j){ foreach(machine m in j { ...}}

    Je voulais que cette requete accepte une autre classe qui ait aussi un GetEnumerator de sorte que ma méthode qui fait ma requête paramétrée tourne avec. Donc je me suis dit pourquoi ne pas passer la méthode comme générique. Et là au niveau de la boucle ça ne passe pas du tout. "L'instruction foreach ne peut pas fonctionner sur des variables de type 'T'. Car 'T' ne contient pas dde définition publique pour 'GetEnumerator'.

    Je pense donc qu'étant donner qu'en passant en générique je ne limite pas ce qu'on peut mettre, ou bien que je ne récupère pas le type en cours de route (et je ne vois pas bien comment faire, un cast me parait impossible, mais surtout l'idée c'est d'automatiser au plus possible et que ça soit polyvalent sans réécrire du code à chaque fois que je crée une nouvelle classe (personne, animal, etc) ) .

    Donc là je sèche pas mal. J'ai rajouté une condition encapsulant le foreach, if(j is IEnumerator){ } mais le compilateur s'en moque royalement.

  2. #2
    Modérateur
    Avatar de DotNetMatt
    Homme Profil pro
    CTO
    Inscrit en
    Février 2010
    Messages
    3 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 37
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : CTO
    Secteur : Finance

    Informations forums :
    Inscription : Février 2010
    Messages : 3 611
    Billets dans le blog
    3
    Par défaut
    Citation Envoyé par daerlnaxe Voir le message
    J'ai créé une classe qui contient un block GetEnumerator. C'est une classe qui ne contient aucune méthode, que des paramètres si je ne me plante pas sur le vocabulaire (get set)
    Ca s'appelle des proprietes, et non des parametres On parle de parametre dans la signature d'une method : public void MyMethod(int a, int b) ici a et b sont des parametres.

    Citation Envoyé par daerlnaxe Voir le message
    Je voulais que cette requete accepte une autre classe qui ait aussi un GetEnumerator de sorte que ma méthode qui fait ma requête paramétrée tourne avec. Donc je me suis dit pourquoi ne pas passer la méthode comme générique. Et là au niveau de la boucle ça ne passe pas du tout. "L'instruction foreach ne peut pas fonctionner sur des variables de type 'T'. Car 'T' ne contient pas dde définition publique pour 'GetEnumerator'.
    Comme tu n'as pas poste ton code, on va faire les devins. Je suppose que tu implementes IEnumerable etant donne que cette interface contient la method GetEnumerator. Tu dois rajouter une contrainte de type (ci-dessous where T : IEnumerable<int>), pour indiquer au compilateur que T implemente/herite un type particulier, en l'occurence IEnumerable. Voici un exemple.

    Ma classe qui implemente IEnumerable<int> via IList<int> :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    class Test : IList<int>
    {
        // Code de la classe ici...
    }
    Le foreach :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    void MyMethod<T>(T listOfNumbers)
        where T : IEnumerable<int>
    {
        foreach (var number in listOfNumbers)
        {
            // On affiche chaque nombre de la liste
            Console.WriteLine(number);
        }
    }
    Utilisation :
    Code C# : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    var listOfNumbers = new Test();
     
    MyMethod(listOfNumbers);
    Less Is More
    Pensez à utiliser les boutons , et les balises code
    Desole pour l'absence d'accents, clavier US oblige
    Celui qui pense qu'un professionnel coute cher n'a aucune idee de ce que peut lui couter un incompetent.

  3. #3
    Membre expérimenté
    Homme Profil pro
    Administrateur Systèmes, Clouds et Réseaux /CAO/DAO/Ingénierie Electrotechnique
    Inscrit en
    Décembre 2014
    Messages
    457
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Administrateur Systèmes, Clouds et Réseaux /CAO/DAO/Ingénierie Electrotechnique

    Informations forums :
    Inscription : Décembre 2014
    Messages : 457
    Par défaut
    désolé oui propriété j'arrive jamais à me souvenir du nom, j'ai même pas percuté que j'utilise le mot paramètres pour ce que je transmets, merci d'avoir rectifié.

    Pour la classe de propriétés, je vais donner un exemple basé sur ce que j'ai fait, l'ID ici je n'en ai pas besoin.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
     
        public class Personne
        {
            public string Table { get; set; }
            public int ID { get; set; }
            public string Nom{ get; set; }
    public int Age{get;set;}
     
     
     
            public IEnumerator<BaseElem> GetEnumerator()
            {           
                yield return new BaseElem { Champ = "nom", Valeur = Nom, DbType = DbType.String };
    yield return new BaseElem{ Champ= "age", Valeur = Age , DbType =DbType.Int32 };
            }
        }
    Pour la méthode de requete paramétrée je sais plus si je l'ai dit mais si j mets dynamic pour le type de paramètre ça fonctionne , peut être que je devrais m'en contenter mais j'aimerai comprendre en fait et selon je suis curieux de voir ce qui est le plus long (sous réserve de trouver une solution pour le cas avec les génériques)


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    public int InsertParam<T> (T j)
    {
    //Tout ce qui faut pour se connecter à la base et initialiser
                        if (j is IEnumerator)
                        {
     
                            foreach (BaseElem m in j)//base elem est un container type qui contient juste le titre du champ, sa valeur et le DbType
     
                            {
                                DbParameter p = rqtInsert.CreateParameter();//rqtInsert est une DbCommand
                                p.ParameterName = m.Champ;
                                p.Value = m.Valeur;
                                p.DbType = m.DbType;
     
                                rqtInsert.Parameters.Add(p); //rqtInsert est une DbCommand
     
                            }// Fin boucle
    //Execution de la requete
                        }
     
    }
    Je te remercie pour l'exemple avec le List, mais ça ne colle pas, c'est peut être moi qui me sert mal de cela.
    Après j'ai lu sur les génériques ce qu'on trouve, dans la journée c'est très probable que je n'ai pas compris l'usage.

  4. #4
    Membre expérimenté
    Homme Profil pro
    Administrateur Systèmes, Clouds et Réseaux /CAO/DAO/Ingénierie Electrotechnique
    Inscrit en
    Décembre 2014
    Messages
    457
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Administrateur Systèmes, Clouds et Réseaux /CAO/DAO/Ingénierie Electrotechnique

    Informations forums :
    Inscription : Décembre 2014
    Messages : 457
    Par défaut
    Je crois que j'ai trouvé, j'ai vu qu'on pouvait mettre des clauses sur les classes génériques, j'ai essayé sur la méthode, j'ai mis "Where T: Personne" sur la méthode d'insertion dans la base. J'ai une erreur ailleurs en cours d'exécution mais ça doit etre lié à autre chose, ça compile en tout cas.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     
    public int InsertParam<T> (T j)where T:Personne

    Edit: code corrigé.
    Le bug arrivé après venait de la condition if(j is iENumerator){} qui encapsulait la boucle, j'avais lu cette solution sur un site en anglais mais ça doit sans doute fonctionner sur une classe qui implémente et pas sur une classe avec juste un bloc. Je précise au cas ou qulqu'un cale comme moi là dessus.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    public int InsertParam<T> (T j)
    {
    //Tout ce qui faut pour se connecter à la base et initialiser
     
     
     
                            foreach (BaseElem m in j)where T: Personne //base elem est un container type qui contient juste le titre du champ, sa valeur et le DbType
     
                            {
                                DbParameter p = rqtInsert.CreateParameter();//rqtInsert est une DbCommand
                                p.ParameterName = m.Champ;
                                p.Value = m.Valeur;
                                p.DbType = m.DbType;
     
                                rqtInsert.Parameters.Add(p); //rqtInsert est une DbCommand
     
                            }// Fin boucle
    //Execution de la requete
     
     
    }

  5. #5
    Membre très actif
    Profil pro
    Inscrit en
    Avril 2008
    Messages
    468
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2008
    Messages : 468
    Par défaut
    Ta clause where T : Personne se met obligatoirement en moment de la déclaration de la méthode générique : public int InsertParam<T> (T j) where T: Personne.

    Sinon tu peux la mettre à la définition de ta classe.... si c'est elle que tu choisis d'être générique - et plus ta méthode.

    Utilises-tu l'aide en ligne ? https://msdn.microsoft.com/fr-fr/library/bb384067.aspx

    Elle explique bien les conditions.

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

Discussions similaires

  1. [Dates] foreach imbrique ?
    Par pascale86 dans le forum Langage
    Réponses: 4
    Dernier message: 17/10/2005, 12h04
  2. Foreach + switch
    Par mic79 dans le forum Langage
    Réponses: 12
    Dernier message: 12/10/2005, 16h36
  3. Réponses: 4
    Dernier message: 14/09/2005, 17h23
  4. [C#] ArrayList, foreach et suppression
    Par lalystar dans le forum Windows Forms
    Réponses: 3
    Dernier message: 06/04/2005, 11h42
  5. [langage] foreach, last et valeurs de sortie
    Par Herode dans le forum Langage
    Réponses: 6
    Dernier message: 01/04/2005, 14h37

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