2008-10-11 9 views
14

Ich versuche über clevere, klare und einfache Wege nachzudenken, Code zu schreiben, der die Folge von ganzen Zahlen in einem gegebenen Bereich beschreibt.Was ist der beste Weg, [0..100] in C# zu schreiben?

Hier ist ein Beispiel:

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

Antwort

62

Dies ist bereits im Rahmen: Enumerable.Range.

Für andere Typen könnten Sie die Bereichsklassen in meiner MiscUtil Bibliothek interessiert sein.

+0

Bad Link hier Jon –

+3

@ Sam:wie verwendet Works für mich, was ist es schlecht ist? –

+2

@Sam: Welche funktioniert nicht für Sie, und was bekommen Sie? –

0

Hier ist eine Idee, die eine Reihe Klasse arbeiten mit beiden Dinge können, die diskrete und solche sind, die nicht sind:

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

Und wenn Sie denken, dass die Aufzählungs Versorgung jedes Mal, hier ist eine abgeleitete Klasse ärgerlich ist:

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

Ich habe gefunden, dass es eine bessere Trennung bietet, um eine Range-Klasse und eine bestimmte RangeIterator-Klasse zu haben. Abgesehen von allem anderen, bedeutet es, dass Ihre Range unveränderlich und versiegelt sein kann, was nett ist. Die Version in MiscUtil hat verschiedene Methoden (Erweiterung und andere), um zwischen den beiden zu gehen. –

+0

Ja, ich habe das in MiscUtil gesehen. Mein Bereich könnte unveränderlich sein; Der einzige Grund für die Wandlungsfähigkeit ist für mich, dass es C# -Objektinitialisierer ermöglicht. Ich hätte wahrscheinlich für die Unveränderlichkeit gehen sollen. –

7

Alternativ kann eine fließend Schnittstelle von Erweiterungsmethoden:

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); 
    } 
} 
1.To(100) 
+0

Persönlich mag ich die Art, wie die Erweiterungsmethode besser liest. Obwohl, ich habe ein bisschen eine weiche Seite für Erweiterungsmethoden (ich habe sie für VB implementiert). Ich habe nie verstanden, warum die C# Leute Range überhaupt nicht zu einer Erweiterungsmethode gemacht haben. –