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

 .NET Discussion :

IEnumerable<T> et méthode IEnumerator GetEnumerator()


Sujet :

.NET

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Août 2008
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 62
    Points : 59
    Points
    59
    Par défaut IEnumerable<T> et méthode IEnumerator GetEnumerator()
    Bonjour,

    Savez-vous pourquoi, dans le code ci-dessous, il n'y a pas - et il n'est à priori pas possible - de préciser la visibilité de la méthode IEnumerator IEnumerable.GetEnumerator() de la classe Fibonacci !?

    D'avance Merci

    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
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace yieldTest
    {
    
        // yield avec une classe implémentant l'interface IEnumerable<T>
        class Fibonacci : IEnumerable<int>
        {
    	    private int[] _numbers = new[] { 0, 1, 1, 2, 3, 5, 8, 13, 21 };
    	
    	    public IEnumerator<int> GetEnumerator()
            {
    		    for( var index=0; index < this._numbers.Length; index++ )
    		    {
            	    yield return this._numbers[index];
    		    }
            }
    
            // IEnumerable<T> héritant de IEnumerable, il est nécessaire d'implémenter cette méthode retournant un IEnumerable.GetEnumerator()
            // Question :
            //      Pourquoi ne précise-t-on pas la visibilité de cette méthode (ni public, protected, etc...) ?
            //      Par défaut, la visibilité devrait être private MAIS si on place un "private" au debut de la déclaration de la méthode : erreur à la compilation
            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
            {
                return (System.Collections.IEnumerator) this.GetEnumerator();
            }
        }
    
        class Program
        {
            // yield cas simple d'une fonction
            static IEnumerable<int> GetFibonacci()
            {
    	        int[] _numbers = new[] { 0, 1, 1, 2, 3, 5, 8, 13, 21 };
    	
    	        for( var index=0; index < _numbers.Length; index++ )
    	        {
    	   	        yield return _numbers[index];
    	        }
            }
    
            static void Main(string[] args)
            {
    	        foreach(var i in GetFibonacci() )
    	        {
    		        System.Console.WriteLine( i );
    	        }
    	        
    	        System.Console.WriteLine( "---" );
    	
    	        foreach(var i in new Fibonacci() )
    	        {
    		        System.Console.WriteLine( i );
    	        }
    
                System.Console.ReadLine();
            }
    
        }
    }
    Sortie :

    0
    1
    1
    2
    3
    5
    8
    13
    21
    ---
    0
    1
    1
    2
    3
    5
    8
    13
    21

  2. #2
    Membre émérite Avatar de meziantou
    Homme Profil pro
    Ingénieur R&D
    Inscrit en
    Avril 2010
    Messages
    1 223
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : Canada

    Informations professionnelles :
    Activité : Ingénieur R&D
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2010
    Messages : 1 223
    Points : 2 439
    Points
    2 439
    Par défaut
    Il s'agit d'une implémentation explicite de l'interface IEnumerable.
    http://msdn.microsoft.com/fr-fr/libr...(v=vs.71).aspx
    http://msdn.microsoft.com/fr-fr/libr...(v=vs.71).aspx

  3. #3
    Membre du Club
    Profil pro
    Inscrit en
    Août 2008
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 62
    Points : 59
    Points
    59
    Par défaut
    Merci pour votre réponse , qui m'apprend quelque chose s'agissant de l'implémentation explicite d'une interface : jusqu'à ce jour, j'implémentais toujours mes interfaces de l'autre façon, que l'on nomme implicite je suppose ? A toute fin utile, en fin de post, j'ajoute un petit bout de code permettant de bien "voir" la différence entre les deux implémentations (bout de code largement inspiré des liens que vous m'avez fourni dans votre post).

    Cependant, il me reste une question : comment sait-on qu'il faut implémenter GetEnumerator (de IEnumerable non générique) de façon explicite ? Est-ce seulement obligatoire, d'ailleurs ? J'ai tendance à penser que "oui", vu que l'implémentation suivante génère une erreur à la compilation :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public System.Collections.IEnumerator GetEnumerator()
    {
        return (System.Collections.IEnumerator) this.GetEnumerator();
    }
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Le type 'yieldTest.Fibonacci' définit déjà un membre appelé 'GetEnumerator' avec les mêmes types de paramètres
    Finalement, il semble surtout qu'il faille implémenter l'une des méthodes de façon explicite, et l'autre de façon implicite ! Sinon erreur à la compilation. Par exemple l'implémentation suivante compile :

    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
    class Fibonacci : IEnumerable<int>
    {
        private int[] _numbers = new[] { 0, 1, 1, 2, 3, 5, 8, 13, 21 };
     
        System.Collections.Generic.IEnumerator<int> System.Collections.Generic.IEnumerable<int>.GetEnumerator()
        {
    		for( var index=0; index < this._numbers.Length; index++ )
    		{
            	yield return this._numbers[index];
    		}
        }
     
        public System.Collections.IEnumerator GetEnumerator()
        {
            var ie = (System.Collections.Generic.IEnumerable<int>)this;
            return (System.Collections.IEnumerator) ie.GetEnumerator();
        }
    }

    Finalement, quel avantage d'avoir deux méthodes ? S'agit-t-il uniquement d'une contrainte lié à cet héritage ? :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public interface IEnumerable<out T> : IEnumerable
    Vos avis, remarques, etc... m'intéresse

    Ci-dessous le bout de code pour l'implémentation implicite versus explicite :

    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
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
     
    namespace ConsoleApplication1
    {
        interface IDimension
        {
            int Largeur();
            int Hauteur();
        }
     
        class Boite
        {
            protected int _largeur;
            protected int _hauteur;
     
            public Boite(int largeur, int hauteur)
            {
                this._largeur = largeur;
                this._hauteur = hauteur;
            }
        }
     
        class BoiteExplicite : Boite, IDimension
        {
            public BoiteExplicite(int largeur, int hauteur) : base( largeur, hauteur ) {}
     
            int IDimension.Largeur() { return this._largeur; }
            int IDimension.Hauteur() { return this._hauteur; }
        }
     
        class BoiteImplicite : Boite, IDimension
        {
            public BoiteImplicite(int largeur, int hauteur) : base(largeur, hauteur) {}
     
            public int Largeur() { return this._largeur; }
            public int Hauteur() { return this._hauteur; }
        }
     
        class Program
        {
            static void Main(string[] args)
            {
                // Explicite
                var be = new BoiteExplicite(3, 4);
                var ie = (IDimension)be;
     
                // Erreur à la compilation : un membre d'interface qui est implémenté de façon explicite n'est pas accessible à partir d'une instance de classe
                //Console.WriteLine("be.Largeur() = " + be.Largeur());
                //Console.WriteLine("be.Hauteur() = " + be.Hauteur());
                Console.WriteLine("ie.Largeur() = " + ie.Largeur());
                Console.WriteLine("ie.Hauteur() = " + ie.Hauteur());
     
                // Implicite
                var bi = new BoiteImplicite(1, 2);
                var ii = (IDimension)bi;
     
                Console.WriteLine("bi.Largeur() = " + bi.Largeur());
                Console.WriteLine("bi.Hauteur() = " + bi.Hauteur());
                Console.WriteLine("ii.Largeur() = " + ii.Largeur());
                Console.WriteLine("ii.Hauteur() = " + ii.Hauteur());
     
                Console.ReadLine();
            }
        }
    }

  4. #4
    Membre confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mars 2011
    Messages
    269
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mars 2011
    Messages : 269
    Points : 460
    Points
    460
    Par défaut
    Bonjour,
    jusqu'à ce jour, j'implémentais toujours mes interfaces de l'autre façon, que l'on nomme explicite je suppose
    Vous vouliez surement écrire implicite.

    comment sait-on qu'il faut implémenter GetEnumerator (de IEnumerable non générique) de façon explicite ? Est-ce seulement obligatoire, d'ailleurs ?
    L'implementation explicite d'une interface n'est nescessaire que lors d'un conflit entre deux (ou plus) interface.
    Comme pour IEnumerable et IEnumerable<T>, qui decrive toutes deux une méthode GetEnumerator().
    Dans ce cas là, on implémente une des interfaces de manière implicite (celle qui sera le plus souvent utilisée), et les autres de manière explicites.

    Dans le cas particulier de IEnumerable, comme un IEnumerator<T> est un IEnumerator, l’implémentation explicite consiste seulement a renvoyer sur celle de IEnumerable<T>.

  5. #5
    Membre du Club
    Profil pro
    Inscrit en
    Août 2008
    Messages
    62
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 62
    Points : 59
    Points
    59
    Par défaut IEnumerable<T> et méthode IEnumerator GetEnumerator()
    Vous vouliez surement écrire implicite.
    Exact, corrigé

    L'implementation explicite d'une interface n'est nescessaire que lors d'un conflit entre deux (ou plus) interface.
    C'est bien ce que j'avais déduit de mes tests

    Merci pour la confirmation, et pour les réponses apportées, je marque le thread comme résolu

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

Discussions similaires

  1. [C#] Méthode d'extension ToUpper à IEnumerable
    Par bilou_12 dans le forum Débuter
    Réponses: 4
    Dernier message: 14/02/2012, 20h29
  2. [C#] créer sa propre méthode d'extension du type IEnumerable
    Par bilou_12 dans le forum Débuter
    Réponses: 3
    Dernier message: 10/02/2012, 15h27
  3. [c#] IEnumerable - IEnumerator
    Par lapanne dans le forum C#
    Réponses: 2
    Dernier message: 31/01/2008, 11h01
  4. Réponses: 7
    Dernier message: 17/12/2007, 18h46
  5. Réponses: 14
    Dernier message: 14/12/2007, 15h56

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