none
FindIndex n'existe pas dans Collection<T> RRS feed

  • Question

  • Bonjour tout le monde,

    Initialement, j'avais crée une classe MaList qui héritait de List<MonType>, elle marche bien.

    j'utilise depuis peu l'outils FxCop pour améliorer divers aspects de mon livrable, lisibilité maintenance , etc.

    et il s'avère que cet outils me recommande d'utiliser la classe Collection<T> à la place de List<T> pour l'héritage (voir http://msdn.microsoft.com/library/ms182142(VS.100).aspx).

    c'est ce que j'ai fait, mais à mon regret je n'ai plus accès à la méthode FindIndex car elle n'existe pas dans cette classe, cela me surprend un peu car je ne comprend pas pourquoi ... 

    Avez vous des idée ? 

    merci d'avance


    PhD - Student
    dimanche 29 août 2010 16:46

Réponses

  • Bonjour,

    Les méthodes d'extensions Linq s'utilise sur des objets implémentant l'interface IEnumerable<T>. L'interface IEnumerable<T> représente une séquence de données qui peut-être parcourue en avant uniquement. L'interface IEnumerable<T> ne définit donc pas de notion "d'index". Il existe une méthode "ElementAt" qui permet de récupérer un objet à un index spécifié, mais cela se fait à l'aide d'un compteur et en parcourant laséquence.

    Si vous souhaitez bénéficier de la méthode FindIndex(), il faut créer une classe dérivée de Collection<T>, ajouter une méthode FindIndex() et cette dernière doit appeler FindIndex() sur la collection interne de la Collection<T> (accessible via la propriété Items).

    Cordialement


    Gilles TOURREAU - MVP C# - MCTS ADO .NET 3.5 - MCPD Windows Developper 3.5 - Architecte .NET/Consultant/Formateur - http://gilles.tourreau.fr
    • Marqué comme réponse OmarioS lundi 30 août 2010 13:53
    lundi 30 août 2010 08:12
    Modérateur
  • Bonjour,

    Lors de l'instanciation de la collection, vous pouvez spécifier la collection interne qui sera utilisée (doit implémenter IList<T>).

    Donc si vous écrivez le constructeur comme ceci :

    public MaCollection
      : base(new List<SymbolicData>())
    {
    }
    

    Vous pouvez écrire votre méthode FindIndex comme ceci :

    public int FindIndex(Predicate<SymbolicData> match)
    {
       return ((List<SymbolicData>)this.Items).FindIndex(match);
    }
    
    

    Cordialement


    Gilles TOURREAU - MVP C# - MCTS ADO .NET 3.5 - MCPD Windows Developper 3.5 - Architecte .NET/Consultant/Formateur - http://gilles.tourreau.fr
    • Marqué comme réponse OmarioS lundi 30 août 2010 14:59
    lundi 30 août 2010 14:39
    Modérateur

Toutes les réponses

  • Bonjour,

    j'utilise depuis peu l'outils FxCop pour améliorer divers aspects de mon livrable, lisibilité maintenance , etc.
    Bonne initiative !

    List<T> permet de représenter des listes (tableaux dynamiques) et propose énormément de services pour rechercher, trier,...etc les éléments contenues dans cette dernière. Les listes ne doivent jamais êtes exposées publiquement. Elles sont utilisées en internet dans les méthodes ou dans les classes.

    Collection<T> permet de représenter une collection d'objet qui peut-être exposé publiquement dans une classe :

    public Collection<T> MaCollection
    {
      get { return this.collection; }
    }
    

    Collection<T> n'offre que très peu de service (ajout, suppression, insertion). Cela est fait volontairement, car étant donné que Collection<T> représente une collection d'objet pouvant être publié publiquement, il faut que le développeur puisse maitriser les opérations qui s'effectuent dessus (Ce qui n'est pas le cas de List<T>).

    Si, vous devez ajouter d'autres services, vous devez créer une classe héritant de Collection<T> (le plus souvent cette classe se termine par Collection, par exemple : VoitureCollection) et ajoutez vos propres méthodes.

    Est-ce que cette nuance vous parait plus limpide ?

    Cordialement


    Gilles TOURREAU - MVP C# - MCTS ADO .NET 3.5 - MCPD Windows Developper 3.5 - Architecte .NET/Consultant/Formateur - http://gilles.tourreau.fr
    dimanche 29 août 2010 17:49
    Modérateur
  • Merci gilles pour votre réponse,

    En effet, je comprends bien l'intérêt de protéger les membres qu'on veut exposer d'une classe publique, surtout quand il s'agit de modifier des éléments d'une instance de la classe MaCollection. 

    Ce qui me surprend c'est que la méthode d'extension First (retourne le premier élément qui vérifie une condition) existe dans Collection<T> mais pas la méthode FindIndex (retourne l'indice du premier élément qui vérifie une condition) qui se ressemble beaucoup à la première.

    Par ailleurs, pour détourner ce problème je peux utiliser la méthode Collection<T>.ToList<T>() pour transformer cette collection en liste est ensuite invoquer la méthode FindIndex sur cette liste.

    Mais je ne suis pas sur que cette façon de faire est bien car je ne sais pas si la méthode ToList<T>() est couteuse [complexité O(n)].  

    dimanche 29 août 2010 23:34
  • Bonjour,

    Les méthodes d'extensions Linq s'utilise sur des objets implémentant l'interface IEnumerable<T>. L'interface IEnumerable<T> représente une séquence de données qui peut-être parcourue en avant uniquement. L'interface IEnumerable<T> ne définit donc pas de notion "d'index". Il existe une méthode "ElementAt" qui permet de récupérer un objet à un index spécifié, mais cela se fait à l'aide d'un compteur et en parcourant laséquence.

    Si vous souhaitez bénéficier de la méthode FindIndex(), il faut créer une classe dérivée de Collection<T>, ajouter une méthode FindIndex() et cette dernière doit appeler FindIndex() sur la collection interne de la Collection<T> (accessible via la propriété Items).

    Cordialement


    Gilles TOURREAU - MVP C# - MCTS ADO .NET 3.5 - MCPD Windows Developper 3.5 - Architecte .NET/Consultant/Formateur - http://gilles.tourreau.fr
    • Marqué comme réponse OmarioS lundi 30 août 2010 13:53
    lundi 30 août 2010 08:12
    Modérateur
  • la propriété Items (de la classe Collection<T>) est enveloppée par l'interface IList<T> qui ne contient pas la méthode FindIndex ...

    du coup finalement j'ai implanté cette méthode 

        public int FindIndex(Predicate<SymbolicData> match)
        {
          for (int index = 0; index < this.Count; index++)
            if (match(this[index])) return index;
          return -1;
        }
    
    comme suggéré içi

     

     

     

     


    PhD - Student
    lundi 30 août 2010 13:38
  • Bonjour,

    Lors de l'instanciation de la collection, vous pouvez spécifier la collection interne qui sera utilisée (doit implémenter IList<T>).

    Donc si vous écrivez le constructeur comme ceci :

    public MaCollection
      : base(new List<SymbolicData>())
    {
    }
    

    Vous pouvez écrire votre méthode FindIndex comme ceci :

    public int FindIndex(Predicate<SymbolicData> match)
    {
       return ((List<SymbolicData>)this.Items).FindIndex(match);
    }
    
    

    Cordialement


    Gilles TOURREAU - MVP C# - MCTS ADO .NET 3.5 - MCPD Windows Developper 3.5 - Architecte .NET/Consultant/Formateur - http://gilles.tourreau.fr
    • Marqué comme réponse OmarioS lundi 30 août 2010 14:59
    lundi 30 août 2010 14:39
    Modérateur
  • Certes c'est plus simple,

    Merci Gilles


    PhD - Student
    lundi 30 août 2010 15:00