2008-10-11 20 views
14

J'essaie de trouver des façons intelligentes, claires et simples d'écrire du code qui décrit la séquence d'entiers dans une plage donnée.Quelle est la meilleure façon d'écrire [0..100] en C#?

Voici un exemple:

IEnumerable<int> EnumerateIntegerRange(int from, int to) 
{ 
    for (int i = from; i <= to; i++) 
    { 
     yield return i; 
    } 
} 

Répondre

62

C'est déjà dans le cadre: Enumerable.Range.

Pour les autres types, les classes de plage de ma bibliothèque MiscUtil peuvent vous intéresser.

+0

Bad lien ici Jon –

+3

@ Sam: travaille pour moi, ce qui est mauvais à ce sujet? –

+2

@Sam: Lequel ne fonctionne pas pour vous, et qu'est-ce que vous obtenez? –

0

est ici une idée qui permet un travail de classe gamme avec les deux choses qui sont discrètes et celles qui ne sont pas:

class Range<T> where T: IComparable<T> 
{ 
    public T From { get; set; } 
    public T To { get; set; } 

    public Range(T from, T to) { this.From = from; this.To = to; } 

    public IEnumerable<T> Enumerate(Func<T, T> next) 
    { 
     for (T t = this.From; t.CompareTo(this.To) < 0; t = next(t)) 
     { 
      yield return t; 
     } 
    } 

    static void Example() 
    { 
     new Range<int> (0, 100).Enumerate(i => i+1) 
    } 
} 
0

Et si vous pensez que fournir le recenseur chaque fois est ennuyeux, voici une classe dérivée:

class EnumerableRange<T> : Range<T>, IEnumerable<T> 
    where T : IComparable<T> 
{ 
    readonly Func<T, T> _next; 
    public EnumerableRange(T from, T to, Func<T, T> next) 
     : base(from, to) 
    { 
     this._next = next; 
    } 

    public IEnumerator<T> GetEnumerator() 
    { 
     return Enumerate(this._next).GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return this.GetEnumerator(); 
    } 
} 
+1

J'ai trouvé qu'il fournit une meilleure séparation pour avoir une classe Range et une classe RangeIterator distincte. En dehors de toute autre chose, cela signifie que votre Range peut être immuable et scellée, ce qui est agréable. La version dans MiscUtil a diverses méthodes (extension et autre) pour aller entre les deux. –

+0

Ouais, j'ai vu celui de MiscUtil. Ma gamme pourrait être immuable; Pour moi, la seule raison de la mutabilité est qu'elle autorise les initialiseurs d'objets C#. Je devrais probablement avoir choisi l'immuabilité. –

7

en variante, une interface fluide à partir de méthodes d'extension:

public static IEnumerable<int> To(this int start, int end) 
{ 
    return start.To(end, i => i + 1); 
} 

public static IEnumerable<int> To(this int start, int end, Func<int, int> next) 
{ 
    int current = start; 
    while (current < end) 
    { 
     yield return current; 
     current = next(current); 
    } 
} 

utilisé comme:

1.To(100) 
+0

Personnellement, j'aime la façon dont la méthode d'extension lit mieux. Bien que, j'ai un peu un côté doux pour les méthodes d'extension (je les ai implémentées pour VB). Je n'ai jamais compris pourquoi les gens de C# n'ont pas fait de Range une méthode d'extension en premier lieu. –