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

VB.NET Discussion :

À propos du For…Each [Débutant]


Sujet :

VB.NET

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre très actif
    Homme Profil pro
    Retraité intello
    Inscrit en
    Juillet 2012
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 84
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Retraité intello

    Informations forums :
    Inscription : Juillet 2012
    Messages : 186
    Par défaut À propos du For…Each
    Bonjour Madame, Monsieur

    Ayant réalisé quelques classes personnelles, j'aimerais maintenant les doter du For…Each, mais je ne sais comment m'y prendre. Quelqu'un pourrais-t-il m'aider ?

    Merci d'avance.

  2. #2
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Salut,

    Que veux-tu faire exactement ? Qu'entends-tu par "les doter du For Each" ?

    Si le but est de pouvoir "parcourir" la classe avec un boucle For Each, il faut implémenter l'interface IEnumerable, ou sa version générique IEnumerable(Of T)

  3. #3
    Membre Expert
    Avatar de Sehnsucht
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Octobre 2008
    Messages
    847
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Octobre 2008
    Messages : 847
    Par défaut
    Citation Envoyé par tomlev Voir le message
    Salut,

    Que veux-tu faire exactement ? Qu'entends-tu par "les doter du For Each" ?

    Si le but est de pouvoir "parcourir" la classe avec un boucle For Each, il faut implémenter l'interface IEnumerable, ou sa version générique IEnumerable(Of T)
    Ça c'est juste un cas particulier des pré-requis nécessaires.

    Pour pouvoir faire un For Each, il faut:
    • Une méthode d'instance GetEnumerator qui retourne un type "Iterable"
    • Ce type Iterable doit posséder:
      • Une propriété Current qui doit retourner le type sur lequel on boucle (ou un type convertible en celui sur lequel on boucle)
      • Une méthode MoveNext qui renvoie un Boolean (True tant q'uon peut itérer)


    Voici un exemple simpliste pour illustrer
    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    Public Class CustomClass
        Private items As Integer()
     
        Public Sub New()
            items = {42, 666, 1234, 0, -42}
        End Sub
     
        Public Function GetEnumerator() As CustomClassEnumerator
            Return New CustomClassEnumerator(Me)
        End Function
     
        ' Représente le type Iterable évoqué dans l'explication
        Public Class CustomClassEnumerator
            Private index As Integer
            Private source As CustomClass
     
            Public Sub New(ByVal src As CustomClass)
                index = -1
                source = src
            End Sub
     
            Public Function MoveNext() As Boolean
                index += 1
                Return index < source.items.Length
            End Function
     
            Public ReadOnly Property Current As Integer
                Get
                    Return source.items(index)
                End Get
            End Property
     
        End Class
    End Class
     
    Sub Main()
        For Each i As Integer In New CustomClass()
            Console.WriteLine(i)
        Next
    End Sub
     
    'Output:
    '42
    '666
    '1234
    '0
    '-42
    Après on peut se contenter de juste faire une méthode GetEnumerator qui renvoie un items.GetEnumerator sans forcément implémenter toute l'interface.

    Cordialement !

  4. #4
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par Sehnsucht Voir le message
    Ça c'est juste un cas particulier des pré-requis nécessaires.

    Pour pouvoir faire un For Each, il faut:
    • Une méthode d'instance GetEnumerator qui retourne un type "Iterable"
    • Ce type Iterable doit posséder:
      • Une propriété Current qui doit retourner le type sur lequel on boucle (ou un type convertible en celui sur lequel on boucle)
      • Une méthode MoveNext qui renvoie un Boolean (True tant q'uon peut itérer)
    C'est juste
    Mais en pratique, je n'ai quasiment jamais vu de classe comme ça qui n'implémente pas IEnumerable. Même si implémenter l'interface ce n'est pas vraiment indispensable en soi, ça a l'avantage d'indiquer clairement que la classe supporte l'énumération. Et ça permet aussi l'utilisation avec Linq...

  5. #5
    Membre Expert
    Avatar de Sehnsucht
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Octobre 2008
    Messages
    847
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Octobre 2008
    Messages : 847
    Par défaut
    On est bien d'accord, c'était plus dans un souci de précision.
    D'ailleurs au passage on peut très bien utiliser Linq "à sa sauce" (ou pas) en réimplémentant les méthodes style SelectMany, Where... (avec les "bons prototypes pour ce que l'on veut) et pour faire d'autres choses (mais c'est une autre histoire ça) ; après dans la majorité des cas on veut le comportement de base donc là la question ne se pose même pas.

    J'ai un peu exploré le sujet, en cherchant à détourner Linq pour d'autres utilisations monadiques.

    Cordialement !

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Citation Envoyé par Sehnsucht Voir le message
    J'ai un peu exploré le sujet, en cherchant à détourner Linq pour d'autres utilisations monadiques.
    Moi aussi j'ai un peu fait joujou avec ça, mais ça dépasse un peu (beaucoup ) le cadre de la question

  7. #7
    Membre très actif
    Homme Profil pro
    Retraité intello
    Inscrit en
    Juillet 2012
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 84
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Retraité intello

    Informations forums :
    Inscription : Juillet 2012
    Messages : 186
    Par défaut
    Bonjour.

    C'est effectivement ce que je veux faire. Je vais essayer ce que vous m'indiquez.

    Merci beaucoup.

  8. #8
    Membre très actif
    Homme Profil pro
    Retraité intello
    Inscrit en
    Juillet 2012
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 84
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Retraité intello

    Informations forums :
    Inscription : Juillet 2012
    Messages : 186
    Par défaut
    Bonjour.

    tomlev a dit en substance
    Pour faire du For Each, implémenter l'interface IEnumerable.
    Soit. J'ai trouvé sur msdn un exemple de code. Je l'ai tant bien que mal adapté à mon cas :
    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    Public Class Bidasse
        Private _Nom As String
        Private _Prn As String
        Private _Sal As Double
     
        Public Property Nom As String
            Get
                Return _Nom
            End Get
            Set(ByVal nNom As String)
                _Nom = nNom
            End Set
        End Property
     
        Public Property Prénom As String
            Get
                Return _Prn
            End Get
            Set(ByVal nPrn As String)
                _Prn = nPrn
            End Set
        End Property
     
        Public Property Salaire As Double
            Get
                Return _Sal
            End Get
            Set(ByVal nSal As Double)
                _Sal = nSal
            End Set
        End Property
     
    End Class
    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
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    Imports System.Collections.Generic
    Public Class Adjudant
        Implements IEnumerable
        Private Col As System.Collections.Generic.List(Of Bidasse)
        Private _Nom As String
        Private _Prn As String
        Private _Sal As Double
     
        Public Sub New()
            Col = New System.Collections.Generic.List(Of Bidasse)
        End Sub
     
        Public Function Nombre() As Integer
            Return Col.Count
        End Function
     
        Default Public ReadOnly Property Item(ByVal Rng As Integer) As Bidasse
            Get
                Return Col.Item(Rng)
            End Get
        End Property
     
        Public Sub Ajouter(ByVal Infé As Bidasse)
            Col.Add(Infé)
        End Sub
     
        Public Sub Retirer(ByVal Rng As Integer)
            Col.RemoveAt(Rng)
        End Sub
     
        Public Sub Vider()
            Col.Clear()
        End Sub
     
        Public Function Rang(ByVal Infé As Bidasse) As Integer
            Dim i As Integer
            For i = 0 To Nombre() - 1
                If Item(i) Is Infé Then Exit For
            Next i
            Return i
        End Function
     
        Public Property Nom As String
            Get
                Return _Nom
            End Get
            Set(ByVal nNom As String)
                _Nom = nNom
            End Set
        End Property
     
        Public Property Prénom As String
            Get
                Return _Prn
            End Get
            Set(ByVal nPrn As String)
                _Prn = nPrn
            End Set
        End Property
     
        Public Property Salaire As Double
            Get
                Return _Sal
            End Get
            Set(ByVal nSal As Double)
                _Sal = nSal
            End Set
        End Property
     
     
     
     
        Private Adj() As Bidasse
     
        Public Sub New(ByVal LstAdj() As Bidasse)
            Adj = New Bidasse(LstAdj.Length - 1) {}
            Dim i As Integer
            For i = 0 To LstAdj.Length - 1
                Adj(i) = LstAdj(i)
            Next i
        End Sub
     
        Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator
            Return New AdjudantEnum(Adj)
        End Function
     
     
     
     
        Public Class AdjudantEnum
            Implements IEnumerator
     
            Public Adj() As Bidasse
     
            Dim i As Integer = -1
     
            Public Sub New(ByVal LstAdj() As Bidasse)
                Adj = LstAdj
            End Sub
     
            Public Function MoveNext() As Boolean Implements IEnumerator.MoveNext
                i = i + 1
                Return (i < Adj.Length)
            End Function
     
            Public Sub Reset() Implements IEnumerator.Reset
                i = -1
            End Sub
     
            Public ReadOnly Property Current() As Object Implements IEnumerator.Current
                Get
                    Try
                        Return Adj(i)
                    Catch ex As IndexOutOfRangeException
                        Throw New InvalidOperationException()
                    End Try
                End Get
            End Property
        End Class
     
    End Class
    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
    23
    24
    Public Class Accueil
        Public Adj As New Adjudant
     
        Private Sub bTst_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles bTst.Click
            ConstruireProgrammme()
            Afficher()
        End Sub
     
        Private Sub ConstruireProgrammme()
            Dim Bid As Bidasse
            Bid = New Bidasse : Adj.Ajouter(Bid)
            Bid = New Bidasse : Adj.Ajouter(Bid)
            Bid = New Bidasse : Adj.Ajouter(Bid)
        End Sub
     
        Private Sub Afficher()
            Dim Bid As New Bidasse
     
            For Each Bid In Adj
                MsgBox(Bid.Nom)
            Next
        End Sub
     
    End Class
    et cela ne fonctionne pas. Quelqu'un pourraît-il m'expliquer pourquoi, et comment y remédier ?

    D'avance merci.

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Par défaut
    Ca veut dire quoi "ne fonctionne pas" ? Il faudrait que tu sois plus précis...

    En tous cas, plusieurs remarques :

    • Il vaudrait mieux implementer IEnumerable(Of T) plutôt que IEnumerable tout court, ça permettrait d'indiquer le type des éléments
    • Puisque tu as une List(Of Bidasse), qui implémente elle-même IEnumerable(Of Bidasse), tu peux te simplifier la vie : dans GetEnumerator, renvoie simplement Col.GetEnumerator(). Ça évite de taper toute l'implémentation de l'énumérateur.
    • Conceptuellement, dire qu'un adjudant est une collection de bidasses, ça me parait pas terrible... Ce sont ses subordonnés, mais ils ne font pas "partie" de lui. Il vaudrait mieux que l'adjudant expose sa collection de bidasses via une propriété :

      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
          Public Property Bidasses As IEnumerable(Of Bidasse)
                  Return Col
              End Get
          End Property
      Et pour l'énumérer, tu fais comme ça :
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
              For Each Bid In Adj.Bidasses
                  MsgBox(Bid.Nom)
              Next

  10. #10
    Membre très actif
    Homme Profil pro
    Retraité intello
    Inscrit en
    Juillet 2012
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 84
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Retraité intello

    Informations forums :
    Inscription : Juillet 2012
    Messages : 186
    Par défaut
    Merci pour votre réponse.

    Au lancement du programme, une erreur apparaît à la ligne 103 de la classe Adjudant.

    J'ai une question indigente. Comment sortir proprement de la discussion après l'envoi d'un message ?

  11. #11
    Expert éminent Avatar de Pol63
    Homme Profil pro
    .NET / SQL SERVER
    Inscrit en
    Avril 2007
    Messages
    14 202
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Puy de Dôme (Auvergne)

    Informations professionnelles :
    Activité : .NET / SQL SERVER

    Informations forums :
    Inscription : Avril 2007
    Messages : 14 202
    Par défaut
    ta classe est une classe de données
    for each est utile sur les collections
    il n'y a aucune raison d'implémenter IEnumerable sur une classe de données, ni de faire un for each dessus
    tu pars sur une mauvaise piste à mon avis, bien que certains t'aient suivi ^^

    si tu veux parcourir tous tes bidasses il te faut juste une instance de collection
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    dim bidasses as new list(of bidasse)
    dim b1 as new bidasse
    bidasses.add(b1)
     
    for each b as bidasse in bidasses
     
    next
    Cours complets, tutos et autres FAQ ici : C# - VB.NET

  12. #12
    Membre très actif
    Homme Profil pro
    Retraité intello
    Inscrit en
    Juillet 2012
    Messages
    186
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 84
    Localisation : France, Vienne (Poitou Charente)

    Informations professionnelles :
    Activité : Retraité intello

    Informations forums :
    Inscription : Juillet 2012
    Messages : 186
    Par défaut
    Bonjour.

    J'ai fait ce que vous m'avez indiqué dans votre avant dernière intervention. Le résultat est exactement ce que je souhaitais.

    Je considère donc que mon problème est résolu, grâce à vous.

    Un grand merci.

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

Discussions similaires

  1. A propos de foreach
    Par vaneck dans le forum Langage
    Réponses: 1
    Dernier message: 18/12/2010, 23h05
  2. demande de precision a propos de "foreach"
    Par wodel dans le forum Langage
    Réponses: 2
    Dernier message: 25/04/2007, 12h30
  3. A propos des modèles d'objet (avec sources)
    Par DevX dans le forum C++Builder
    Réponses: 14
    Dernier message: 01/12/2002, 12h22
  4. Fonctionnement de la compression DivX
    Par Rodrigue dans le forum Algorithmes et structures de données
    Réponses: 2
    Dernier message: 20/09/2002, 14h10
  5. A propos du composant DBGrid
    Par _Rico_ dans le forum C++Builder
    Réponses: 2
    Dernier message: 24/07/2002, 09h18

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