ProgrammationDéveloppeur de bibliothèques .NET / Développeur VB.NET de niveau intermédiaire

Décrivez les méthodes de mise en œuvre et d'utilisation des itérateurs (terme Enumerable / Iterator) en Visual Basic, ainsi que la façon de créer vos propres collections itérables.

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Historique de la question
Les itérateurs sont devenus une partie importante des langages de programmation avec l'apparition des collections à parcourir. En Visual Basic, depuis la version .NET, la prise en charge de IEnumerable/IEnumerator est disponible, permettant de mettre en œuvre ses propres collections itérables et d'utiliser la boucle For Each pour un accès pratique et concis au contenu des collections.

Problème
De nombreux développeurs se limitent à l'utilisation uniquement des collections intégrées ou n'implémentent pas correctement l'interface IEnumerable, ce qui rend impossible le parcours des objets via For Each. De plus, la gestion de l'état de l'itérateur à travers Current et MoveNext pose des difficultés.

Solution
Pour prendre en charge les itérations, le type doit implémenter l'interface IEnumerable (ou IEnumerable(Of T) générique). Implémentez la fonction GetEnumerator, retournant un objet implémentant IEnumerator. En VB.NET, des méthodes d'itérateur peuvent également être appliquées avec le mot clé Yield (à partir de VB 2015), ce qui simplifie considérablement l'implémentation du parcours.

Exemple de code:

Imports System.Collections Public Class SimpleCollection Implements IEnumerable Private arr() As Integer = {1, 2, 3} Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator For Each i In arr Yield i ' pour VB 2015+ Next End Function End Class ' Utilisation: For Each n As Integer In New SimpleCollection() Console.WriteLine(n) Next

Caractéristiques clés:

  • Pour prendre en charge For Each, le type doit implémenter IEnumerable / IEnumerable(Of T).
  • L'implémentation est généralement déléguée à une collection existante ou une propre est créée.
  • Avec Yield, on peut créer des itérateurs facilement; sans Yield, on devra implémenter IEnumerator manuellement.

Questions pièges.

Est-il nécessaire d'implémenter les deux interfaces: IEnumerable et IEnumerator, pour prendre en charge For Each ?

Non, l'implémentation de IEnumerable et le retour d'un itérateur compatible suffisent. Si vous souhaitez implémenter le parcours, vous pouvez utiliser l'IEnumerator existant de la collection imbriquée. Mais pour une personnalisation complète, les deux parties doivent être implémentées.

Exemple de code:

Public Function GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator Return arr.GetEnumerator() ' utilise l'itérateur intégré du tableau End Function

Peut-on implémenter IEnumerable uniquement explicitement (Explicit Interface Implementation) en Visual Basic ?

Oui, on peut implémenter l'interface de manière explicite, surtout si votre collection a déjà son propre GetEnumerator, et que vous souhaitez cacher l'implémentation de l'interface. Appeler un tel GetEnumerator directement ne sera pas possible, mais For Each fonctionnera.

Exemple de code:

Public Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator ' ...corps de méthode End Function

Que se passe-t-il si GetEnumerator retourne Nothing ?

Une exception sera levée lors de la première tentative de parcours de la collection, car For Each s'attend à un itérateur valide.

Erreurs typiques et anti-patterns

  • Implémentation incorrecte des méthodes MoveNext/Current, entraînant le fait de sauter des éléments ou de provoquer une erreur.
  • État de l'itérateur violé entre les appels (par exemple, l'index n'est pas réinitialisé lors d'un parcours répétitif).
  • Exception StopIteration absente ou incorrecte.

Exemple de la vie réelle

Cas négatif

La classe de collection n'a pas implémenté IEnumerable, et une méthode séparée Next a été créée pour parcourir les éléments. En fin de compte, elle ne peut pas être utilisée dans des méthodes universelles ou For Each, il faut écrire des méthodes supplémentaires.

Avantages :

  • Mise en œuvre rapide pour la tâche.

Inconvénients :

  • Impossible d'utiliser For Each et LINQ.
  • Perte de compatibilité avec l'API .NET.

Cas positif

Le développeur a implémenté IEnumerable et GetEnumerator, la collection fonctionne maintenant avec For Each et s'intègre avec LINQ.

Avantages :

  • Super compatibilité avec l'infrastructure .NET.
  • Polyvalence et facilité d'utilisation.

Inconvénients :

  • Nécessite un peu plus de code lors de l'implémentation manuelle avant l'apparition de Yield.