2009-07-23 7 views
8

J'essaye de compiler le code suivant mais je reçois des erreurs dans VS2008. Tout le monde peut me dire où je vais mal?IEnumerable <T> en C#

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace dummy 
{ 
    public class NaturalNumbersSequence : IEnumerable<int> 
    { 
     public IEnumerator<int> GetEnumerator() 
     { 
      for (int i = 1; i <= 1000; i++) 
       yield return i; 
     } 

     IEnumerator IEnumerable.GetEnumerator() 
     { 
      for (int i = 1; i <= 1000; i++) 
       yield return i; 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      foreach (int i in new NaturalNumbersSequence()) 
       Console.WriteLine(i); 
     } 
    } 
} 
+12

Notez que c'est une bonne idée de publier les messages d'erreur que vous obtenez également. –

Répondre

24

Eh bien, la première erreur du compilateur que je reçois est qu'il se plaint que:

L'utilisation du type générique de 'System.Collections.Generic.IEnumerator' exige '1' arguments de type

Ceci est la ligne 16, celle-ci:

IEnumerator IEnumerable.GetEnumerator() 

de fixation que par l'ajout d'un nous Directive ing pour l'espace de noms System.Collections (Conseil: placez le curseur juste après IEnumerator, sur r à la fin du mot, puis appuyez sur Ctrl +. (ctrl + la dot-key), il devrait vous suggérer d'ajouter un "using System.Collections;" directive, faites-le).

Ensuite, il compile et s'exécute. Est-ce que cela correspond à ce que vous attendez? De plus, notez que vous devriez toujours publier les vrais messages d'erreur, de cette façon, nous n'aboyons pas le mauvais arbre s'il y a quelque chose d'autre qui ne va pas dans votre code et que nous ne voyons pas au premier coup d'œil.

De plus, vous pouvez simplifier la mise en œuvre très commun de IEnumerable<T> en appelant l'une des méthodes de l'autre, d'où je simplifier la mise en œuvre des deuxième méthodes comme celle-ci:

IEnumerator IEnumerable.GetEnumerator() 
{ 
    return GetEnumerator(); // this will return the one 
          // available through the object reference 
          // ie. "IEnumerator<int> GetEnumerator" 
} 

cette façon vous ne mettre en œuvre le code d'énumérateur réel une fois.

Et enfin voir Earwickeranswer ainsi, il montre une meilleure (à mon avis au moins) moyen d'écrire tout ce code.

+1

+1. La dernière partie sur la réutilisation d'une implémentation de l'énumérateur de l'autre est la cerise sur le gâteau. –

+0

pourquoi y a-t-il 2 implémentations de l'énumérateur en premier lieu? – fcuk112

9

Vous ne savez pas pourquoi vous obtenez des erreurs, mais ce ne serait pas plus simple?

public static class NumbersSequence 
{ 
    public static IEnumerable<int> Naturals 
    { 
     get 
     { 
      for (int i = 1; i <= 1000; i++) 
       yield return i; 
     } 
    } 
} 

class Program 
{ 
    public static void Main(string[] args) 
    { 
     foreach (int i in NumbersSequence.Naturals) 
      Console.WriteLine(i); 
    } 
} 
+5

Et pourquoi arrêter à mille?! –

+12

Tout le monde sait que les nombres supérieurs à 1000 sont anormalement élevés. –

+2

Pour moi, la distinction entre les numéros "réguliers" et "grands" est à vingt mille. Je suppose que c'est une chose de «mise en œuvre». –

4

légèrement hors-sujet, mais peut-être intéressant de voir est cette approche:

public static class NumbersSequence 
{ 
    public static IEnumerable<int> Naturals 
    { 
     get 
     { 
      int i = 0; 
      while(true) 
       yield return i++; 
     } 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     foreach (int i in NumbersSequence.Naturals.Take(1000)) 
      Console.WriteLine(i); 
    } 
} 

C# 3.0 afaik. Faites attention à la boucle apparemment infinie dans le getter, et l'appel à prendre (1000). Avec cette méthode, vous avez maintenant une séquence «infinie» de nombres naturels (sans fin jusqu'à la valeur max d'un int). Il ne sera pas bloqué, tant que vous lui dites de prendre une quantité spécifique.

AVIS DE NON-RESPONSABILITÉ: La plus grande partie du code emprunté à la réponse d'Earwicker.

+1

Alors qu'est-ce que 'i' dans' Naturals.get'? –

+1

Toujours agréable de voir des boucles «infinies» en action. –

+1

Comme Pavel l'a remarqué, il vous manque l'initialisation et l'incrément de i. –

2

Lasse a la bonne réponse, et je sais que ce code est en apprentissage, mais dans l'intérêt de favoriser votre apprentissage Je veux parler de deux choses:

  1. Enumerable.Range()
  2. Prenez le temps de penser à ce mise en oeuvre:

.

public class NaturalNumbersSequence : IEnumerable<int> 
{ 
    public IEnumerator<int> GetEnumerator() 
    { 
     for (int i=0 i <= int.MaxValue;i++) 
      yield return i; 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     for (int i=0 i <= int.MaxValue;i++) 
      yield return i; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     foreach (int i in new NaturalNumbersSequence().TakeWhile(i => i<=1000)) 
      Console.WriteLine(i); 
    } 
} 
Questions connexes